【问题标题】:Dereference Pointer to MxArray指向 MxArray 的取消引用指针
【发布时间】:2014-10-28 09:36:55
【问题描述】:

我遇到了一些指针混淆:

我有一些(数值配方)C 函数 fitexy(in, &out),我想将其编译为 .mex 文件,以便从 matlab 中调用它。但是,我无法让网关例程访问 Pointerout 以便将其传递给 plhs[0],我该怎么做?

我得到的最接近的(在最不令人困惑的错误消息的意义上)是这样的:

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[]){
float *in;
float out;

in      = (float *)mxGetData(prhs[0]);
plhs[0] = mxCreateNumericMatrix(1,1,mxSINGLE_CLASS,mxREAL);
out     = (float *)mxGetData(plhs[0]);

fitexy(in, &out);

printf("out = %lf", &out); /*Prints the correct result to the screen*/
}

这会导致编译时出现错误消息:

error: incompatible types when assigning to type ‘float’ from type ‘float *’

这对我来说并不太令人惊讶,但也不是很有帮助。我试图转换/取消引用mxGetData(plhs[0]) 的输出,

out     = (float &)mxGetData(plhs[0]);

这似乎是一种废话,

out     = (float)mxGetData(plhs[0]);

这与 out 是变量和 mxGetData(plhs[0]) 指针冲突。

我已经找到 Save a variable (float *) to plhsHow to return a float value from a mex function, and how to retrieve it from m-file?,但它们都处理强制转换而不是取消引用。

我了解cannot convert parameter 2 from 'mxArray **' to 'mwArray &',但这对我没有帮助,因为我不能(即不希望)更改对我的 C 例程的调用。

非常感谢任何帮助,非常感谢!

【问题讨论】:

    标签: c matlab pointers mex


    【解决方案1】:

    为什么不直接将out 定义为指针?

    float * out;
    

    这样你就可以轻松搞定

    out     = (float *)mxGetData(plhs[0]);
    

    您可以使用out 来写入结果值。如果我没记错fitexy() 函数,你可以调用它

    fitexy(in, out);
    

    .

    【讨论】:

    • 我只是坚持使用从文件中读取out 的原始代码(需要复制到内存中)。限时后将接受您的超快速回答。非常感谢!
    • 正如@Amro 指出的那样,子程序必须被称为fitexy(in, out);
    【解决方案2】:

    假设您有一个 C 函数 fit_line,其签名如下:

    void fit_line(float x[], float y[], int n, float *a, float *b);
    

    它需要两个长度为n的输入数据数组xy,并通过计算数量ableast-squares sense中拟合一条直线y = a*x + b

    这是我将如何编写 MEX 函数:

    mex_fit_line.c

    #include "mex.h"
    
    EXTERN_C void fit_line(float x[], float y[], int n, float *a, float *b);
    
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    {
        /* validate inputs */
        if (nrhs!=2 || nlhs>2)
            mexErrMsgIdAndTxt("mex:err", "wrong num args");
        if (!mxIsSingle(prhs[0]) || mxIsComplex(prhs[0]) || mxIsSparse(prhs[0]) ||
            !mxIsSingle(prhs[1]) || mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]))
            mexErrMsgIdAndTxt("mex:err", "expecting dense real single arrays");
        if (mxGetNumberOfElements(prhs[0]) != mxGetNumberOfElements(prhs[1]))
            mexErrMsgIdAndTxt("mex:err", "length dont match");
    
        /* get data arrays */
        mwSize len = mxGetNumberOfElements(prhs[0]);
        float *x = (float*) mxGetData(prhs[0]);
        float *y = (float*) mxGetData(prhs[1]);
        if (x==NULL || y==NULL) mexErrMsgIdAndTxt("mex:err", "null ptr");
    
        /* call external function */
        float a, b;
        fit_line(x, y, len, &a, &b);
    
        /* assign output */
        plhs[0] = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
        *((float*) mxGetData(plhs[0])) = a;
        if (nlhs>1) {
            plhs[1] = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL);
            *((float*) mxGetData(plhs[1])) = b;
        }
    }
    

    编译完成后,我们可以在 MATLAB 中调用 MEX 函数为:

    % some random data
    x = randn(100,1,'single');
    y = -1.5*x + 1 + randn(size(x),class(x))*0.9;
    
    % fit least-square line
    [a,b] = mex_fit_line(x,y);
    
    % plot data and fitted line
    xx = linspace(min(x), max(x), 50);
    yy = a*xx + b;
    plot(x, y, 'b.')
    line(xx,yy, 'Color','r')
    axis equal, legend({'data', 'LS line'})
    title(sprintf('y = %.2f*x + %.2f', a, b)), xlabel('X'), ylabel('Y')
    

    【讨论】:

    • 这是一个更完整的答案。然而——在我看来——*((float*) mxGetData(prhs[0])) = a; 看起来有点乱。 float *out = (float *)mxGetData(plhs[0]); 也能做到这一点。
    • 好吧,如果你想保存一些变量,你可以直接调用上面的函数:fit_line(x, y, len, (float*) mxGetData(plhs[0]), (float*) mxGetData(plhs[1]));(假设你之前已经创建了输出数组)并去掉@ 987654336@ 和 b 浮动
    • @wsj:我发布了一个完整的例子也是有原因的,在你的情况下,你必须在完成float *out = (float *)mxGetData(plhs[0]);之后调用fitexy(in, out); not fitexy(in, &out);
    • 你是对的,否则它不会编译。我将此添加到接受的解决方案中。
    猜你喜欢
    • 1970-01-01
    • 2013-01-04
    • 1970-01-01
    • 2012-03-25
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 2011-12-10
    • 1970-01-01
    相关资源
    最近更新 更多