matlab mex: доступ к данным

#matlab #mex

#matlab #mex

Вопрос:

Привет, я действительно не понимаю, как получить доступ к данным, передаваемым через аргументы в matlab в mex-функцию. Предполагая, что у меня есть функция шлюза по умолчанию

 void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
  

И теперь я получаю указатель на аргумент 1. input:

 double* data_in;
data_in = mxGetPr(prhs[0]);
  

Обе следующие строки, каждая отдельно, приводят к сбою моего matlab:

 mexPrintf("%d", *data_in);
mexPrintf("%d", data_in[1]);
  

Но почему я не могу получить доступ к данным таким образом, когда data_in, очевидно, является указателем на первый аргумент?

  1. Когда мне нужно объявлять указатель как double *, а когда как mxArray *? Иногда я вижу что-то вроде этого: mxArray *arr = mxCreateDoubleMatrix(n, m, mxREAL);!?

Заранее большое спасибо!

Ответ №1:

data_in является указателем на double , поэтому вам нужно что-то вроде

 mexPrintf("%f", data_in[0]);
  

Предполагается, что вызывающий объект передал вектор или матрицу размером > 0.

В более общем плане, вы можете

 int n = mxGetN(array);
int m = mxGetM(array);
  

Чтобы получить количество строк и столбцов матрицы / вектора, переданных в функцию mex.

Что касается mxArray :

Matlab упаковывает свои матрицы (сложные и вещественные) в структуру mxArray. mxCreateDoubleMatrix возвращает указатель на такую структуру. Чтобы фактически получить доступ к этим данным, вам нужно использовать mxGetPr () для действительной части и mxGetPi () для мнимых частей.

Они возвращают указатели на выделенные double[] массивы, которые вы можете использовать для доступа (чтения и записи) к элементам матрицы.

Комментарии:

1. Да, я тоже так думал, но когда я использую mexPrintf("%f", data_in1[0]); в своем mexfile, это приводит к сбою matlab…: «———————————————————————— Нарушение сегментации обнаружено в чт, апрель 28 11:45:00 2011 ————————————————————————»

2. @bjoern: убедитесь, что указатель, возвращаемый из mxGetPr, не равен нулю (0) и что mxGetN и mxGetM возвращают числа >= 1

3. Хорошо, спасибо, теперь это работает хорошо! Но у меня есть еще один вопрос: предполагая, что я передаю матрицу через myfunction([1:2; 3:4]) Интересно, почему я не могу получить доступ к данным подобным образом (после in = mxGetPr(prhs[0]); ): mexPrintf("%f", in[0][0]); вместо этого я должен использовать ‘single’-индексирование подобным образом: в [3] вернет 4, а в[0] вернет 1. Почему нет более «очевидной» двойной индексации, как в [n] [m]?

4. @bjoern: Вы можете получить доступ к массиву в C, используя обозначение x [строка] [столбец], только если компилятор знает количество столбцов в строке во время компиляции (поэтому он может переписать это как x [строка * элемент_пер_роу столбец]). Поскольку размерность массива Matlab заранее неизвестна, вы не можете использовать обозначение x[][]. Если вы пишете c , вы можете обернуть mx_array в класс и изменить подходящий operator(), чтобы вы могли получать доступ к элементам, таким как x (строка, столбец).

5. Так это действительно поведение, каким оно должно быть? 🙂

Ответ №2:

Очень удобным способом обработки измерений mxArrays является введение функции, подобной следующей.

 #include <cstddef>
#include <cstdarg>
#include "mex.h"

bool mxCheckDimensions(const mxArray* mx_array, size_t n_dim,...) {
    va_list ap;             /* varargs list traverser */

    size_t *dims;           /* dimension list */
    size_t i;
    size_t dim;
    bool retval = true;

    va_start(ap,n_dim);
    dims = (size_t *) malloc(n_dim*sizeof(size_t));

    for(i=0;i<n_dim;i  ) {
        dims[i] = va_arg(ap,size_t);
        dim  = mxGetDimensions(mx_array)[i];
        if (dim != dims[i])
            retval = false;
    }

    va_end(ap);
    free(dims);

    return retval;
}
  

Таким образом, вы проверяете, является ли массив mxArray * p двойным массивом размером, скажем, 1,3, используя

 double* pDouble = NULL;

if (mxIsDouble(p)) {
    if (mxCheckDimensions(p, 2, 1, 3)) {
        pDouble = (double*) GetData(p);
        // Do whatever
    }
}`