【问题标题】:Matlab engine function in C returns zeroC中的Matlab引擎函数返回零
【发布时间】:2018-07-20 19:27:05
【问题描述】:

我想知道是否有人可以帮助我理解 C 语言中 Matlab 引擎的语法。我是 C 语言的初学者,正在尝试使用 Matlab 引擎在 C 语言中调用自定义 Matlab 函数。我所做的研究包括阅读 Matlab API 的文档、观看 Mathworks 的讲座视频、研究 Stack Overflow、阅读 Matlab 中的示例 eng.c 文件和 Google。

我想出了这段代码,它可以编译但输出返回零。输入数组也不返回数组,而是返回一个 int。我找不到关于如何构建 C 脚本的全面演练视频

  1. 接受一个向量
  2. 将其输入 Matlab 函数并
  3. 返回输出。

文档非常清楚地解释了创建数组,但我找不到详细说明将数组读取到 Matlab 中然后获取输出的信息。

下面,请查看包含 cmets 的代码,了解我理解的每个代码部分的作用。示例函数add_up 只是在数组上调用sum 函数。任何帮助都会很棒,因为我不知道为什么返回零。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "engine.h"
#define BUFSIZE 256

int main() {

    //Open call to matlab engine
    Engine *ep;

    //Use this conjunction with define BUFSIZe 256 to create double
    //extData is a variable to read external data
    //Number in brackets refer to size
    //We are using double in this case and create the external data using initialization
    double extData[10]={1.0,4.0,7.0,2.0,5.0,8.0,3.0,6.0,9.0,10.0};

    //Next step is to make a pointer of type mxArray 
    //These are pointers to an array of any size or type
    mxArray *pVarNum;
    double *outp;

    //After we make a matrix for the double data initialized above
    //Initialized to 0
    pVarNum=mxCreateDoubleMatrix(1,10,mxREAL);

    //Our array needs to be assigned a variable name for Matlab
    //Workspace
    //const char *myDouble = "T";

    //Our matlab matrix is initialized to zero. We need to use
    //The C memcpy function to get the data from extData to
    //Get the array data using the pointer to pVarNum
    //Use mxGetPr, a mxGet function
    memcpy((void *)(mxGetPr(pVarNum)), (void *)extData,sizeof(extData));

    //Place the variable T into the Matlab workspace
    engPutVariable(ep,"T",pVarNum);

    //Evalute test function
    engEvalString(ep, "out=T+1");

    //Make a pointer to the matlab variable
    outp=engGetVariable(ep,"out");
    //Now make a pointer to the C variable
    printf("%d\n",outp);

    printf("Done!\n");
    mxDestroyArray(pVarNum);

    engClose(ep);

    return EXIT_SUCCESS;

}

【问题讨论】:

    标签: c matlab matlab-engine


    【解决方案1】:

    engGetVariable 函数返回 mxArray*,而不是 double*

    double *outp;
    /* ... */
    outp = engGetVariable(ep, "out");
    printf("%d\n", outp);
    

    这应该是:

    mxArray *out;
    double *outp;
    int ii;
    /* ... */
    out = engGetVariable(ep, "out");
    outp = mxGetPr(out);
    for (ii = 0; ii < 9; ii++) {
       printf("%f, ", outp[ii]);
    }
    printf("%f\n", outp[9]);
    

    还要注意printf 中的%d 格式化程序会打印一个int,您需要使用%f 作为双精度数。

    【讨论】:

    • 感谢您的回复,感谢您提供的信息。我按照建议修改了代码,如果我写 printf("%f",output),它现在将打印 0。但是,如果我尝试以任何方式访问 outp 的元素,它就会说存在分段错误,我查找它以表明指针内存访问存在问题。我猜这在某种程度上意味着 outp 不是双重的?您答案中的其他所有内容都是正确的,只是不会给我加倍的回报。
    • 有趣...out 是 NULL 指针,还是 outp 是 NULL 指针? engGetVariable 如果“请求失败”返回 NULL(我猜这意味着请求的变量不存在?),如果 mxArray 没有真正的组件,或者不是数字,mxGetPr 将失败.据我所知,这些都没有发生在这段代码中。
    • 感谢您的快速回复。我检查了输入 pVarNum 和输出。你说得对,out 有问题。它返回 Null,即使 pVarNum 不是 Null。我试图找到一种方法来访问 pVarNum 的元素以确保 memcpy 正常工作,即使它是从 api 手册中完全复制的。任何其他调试技巧也将不胜感激。
    • pVarNum 包含 extData 中的元素。因此,结论似乎是 Matlab 中的计算存在问题,因此它返回 Null。我不知道为什么会这样,因为我只是在示例中为数组的每个数字加一。
    • @Lee:检查engPutVariable的返回值(应该返回“成功返回0,出错返回1”)。如果 engEvalString 导致 MATLAB 内部出现错误,它不会告诉您(尽管在您的情况下它确实不会失败,只要存在 T,如果 engPutVariable 成功,它应该存在)。有关在这种情况下如何调试问题的一些想法,请参阅 here
    【解决方案2】:

    问题是 engputVariable 返回 1,因此 Matlab 引擎没有接收数组。我最终从 Matlab engdemo.c 中复制并粘贴了最上面的代码段(直到调用 engPutVariable),然后继续我的代码。工作代码文件的编码为 ASCII。我认为关键部分是使用 Null 字符串打开 Matlab 的初始调用,尽管我将这段确切的代码放在非工作脚本中,它并没有导致 engPutVariable 工作。

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include "engine.h"
    #define  BUFSIZE 256
    
    int main()
    
    {
        Engine *ep;
        mxArray *T = NULL, *outp = NULL;
        double *out;
        int ii;
        char buffer[BUFSIZE+1];
        double time[10] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0 };
    
    
        if (!(ep = engOpen(""))) {
            fprintf(stderr, "\nCan't start MATLAB engine\n");
            return EXIT_FAILURE;
        }
    
        T = mxCreateDoubleMatrix(1, 10, mxREAL);
        memcpy((void *)mxGetPr(T), (void *)time, sizeof(time));
    
        engPutVariable(ep, "T", T);
    
    
        //Evalute test function. This is new
    
        engEvalString(ep, "D=add_up(T);");
    
        //Make a pointer to the matlab variable
        if((outp=engGetVariable(ep,"D"))==NULL){
            printf("Oops!");
        }
        out= mxGetPr(outp);
    
        //Now make a pointer to the C variable
        for (ii=0; ii<10; ii++) {
            printf("%f\n", out[ii]);
        }
        printf("%f\n",out[2]);
    
        printf("Done!\n");
        mxDestroyArray(T);
        mxDestroyArray(outp);
        engClose(ep);
    
        return EXIT_SUCCESS;
    
    }
    

    【讨论】:

      猜你喜欢
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 2016-03-17
      • 2016-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多