在Matlab中调用C ++函数,处理二维数组,指针指针?

时间:2014-12-23 06:01:00

标签: c++ matlab pointers matrix mex

我试图在Matlab中调用C ++中的函数,我以为我已经正确地编写了我的函数。我想调用的函数看起来像这样,它有8个参数作为输入。

void LimitedPrice(double &dMarketPosition, double** dmatLimitPrice, 
                  char* FileID, double* dvecOpen, double* dvecClose, 
                  double** dmatTempData, int tick, double dMaxBarBack)
 {Bla, Bla, Bla}

我希望在运行此功能后获得2个值。其中存储在dMarketPosition和dmatLimitPrice中,因为它们是指针。

在这个函数中,我必须使用一些**(双指针)来表示我的Matrix。

运行此功能后, dMarketPosition,dmatLimitPrice 将存储我想要的内容,因为它们是指针。我测试了我的功能,我相信我的功能写得很好。

现在我准备好编写 mexFunction()了。 我的mex功能看起来像这样

void mexFunction(int nlhs, mxArray *plhs[],
             int nrhs,const mxArray *prhs[])
{
    if(nrhs!=8){
          mexErrMsgIdAndTxt("LimitPrice: ","I want to 8 inputs");
    }
    // I want two output
    if(nlhs!=2) {
        mexErrMsgIdAndTxt("LimitPrice: ","I want to 2 outputs");
    }

   //The first input is a scalar
   double dmarketposition;
   dmarketposition = mxGetScalar(prhs[0]);

   //The second input is a 2-dimensional Matrix
   double **dmatlimitprice;
   *dmatlimitprice = mxGetPr(prhs[1]);

   /*****Assuming I have checked other inputs here properly*****/
   // I want to define my outputs
   // Create 1*1 matrix as output, which is the double value I want 
   plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
   //The second output is a two dimensional matrix
   plhs[1] = mxCreateDoubleMatrix(2,(mwSize)4,mxREAL);
   dmarketposition = mxGetScalar(plhs[0]);
   *dmatlimitprice = mxGetPr(plhs[0]);
   // Call the function
   LimitedPrice(dmarketposition, dmatlimitprice, fileid,
   dvecopen, dvecclose, dmattempdata, tick, dmaxbarback);
}

以上功能似乎不起作用......似乎在mexFunction()中, 我们最好只传递一维数组,这是一个双倍的东西。

我的关键问题是“我们如何处理二维数组,这是mexFunction()中的矩阵”

2 个答案:

答案 0 :(得分:2)

在内存中,Matlab将所有mxArray列作为一列连续内存逐列存储。在这方面,1D向量和N-D阵列之间没有区别,它们都存储为单个内存块。
例如,考虑内存中的以下块:{ 1, 2, 3, 4, 5, 6, 7, 8 }
它可以被视为1×8,8×1,2×4,4×2或甚至2×2×2阵列。更改数组的shapereshape - ing)不需要更改存储数据的实际内存,只需更改mxArray的“标题”。

您可以做的是在内部分配2D矩阵,调用LimitedPrice,然后将结果复制到输出mxArray,将其从内部double**表示转换为double* mxArray代表。


附注,在您的示例代码中,您分配dmarketpositiondmatlimitprice两次:一次来自第一个和第二个输入,一次来自新分配的输出 - 第二个分配只是覆盖第一个和它看起来您的函数LimitedPrice无法获取存储在mexFunction输入中的信息。

答案 1 :(得分:1)

制作数组2D(或除1D以外的任何大小)的唯一因素是存储在mxArray结构中的数组的形状。所有数据都是连续的。 MATLAB(和mxArray s)中2D数组的步幅或列间字节数始终为number_of_rows * element_size。对于列主存储系统,这是一种说明连续数据缓冲区用于存储所有数组的方式。

mxArray

获取阅读的基本功能
double* mxGetPr(const mxArray*);    // get pointer to start of double buffer
void*   mxGetData(const mxArray*);  // get pointer to start of any data-type buffer
size_t  mxGetM(const mxArray*);     // get number of rows
size_t  mxGetN(const mxArray*);     // get number of columns

没有像OpenCV's T* ptr<T>(int i)这样的函数来获取指向指定行(或MATLAB中的列)的指针。要获取元素,您只需访问位置irow + icol*numRows即可。这就是为什么在C / C ++中有一个类似sub2ind的函数的常见原因:

inline mwSize sub2ind(mwSize irow, mwSize icol, mwSize numRows) {
    return irow + icol*numRows; }

这是通用建议,没有特定于您的代码。由于LimitedPrice()的语义不明确,我对提出具体建议犹豫不决。语法很明确 - 它需要指向指针的指针 - 但通常使用**来返回新指针(内部分配的结果)而不是管理2D数组。如果它的2D数据通常会有两个整数类型来指定尺寸,但我不会看到它。

由于上述原因,很难提供更具体的帮助,但这里有一个很大的问题需要解决:

double **dmatlimitprice;
*dmatlimitprice = mxGetPr(prhs[1]);  // dereferencing uninitialized pointer, ERROR

可以创建一个double**作为输入矩阵列的索引(如果这是你真正需要的那些!)。例如:

size_t numCols = mxGetN(prhs[1]);
double *dlimitBuffer = mxGetPr(prhs[1]);
// Simulate a 2D array:
std::vector<double*> dlimitvec(numCols);
double **dmatlimitprice = &dlimitvec[0]; // or = new double*[numCols]; if you delete[]
for (size_t i=0; i < numCols; ++i)
    datalimitprice[i] = dlimitBuffer + i*numRows;

假设您需要double**,其中每个double*指向某个矩阵的各列,这可能不正确,因此请将此视为示例。您也可能需要转置矩阵。

此外,您对*dmatlimitprice进行了两次无效分配,因此很难判断您是否希望将其作为输入或输出数组。