如何在从 Matlab 调用的 mex 函数中使用 Matlab 引擎
Posted
技术标签:
【中文标题】如何在从 Matlab 调用的 mex 函数中使用 Matlab 引擎【英文标题】:How can I use Matlab engine in a mex function called from Matlab 【发布时间】:2012-03-07 12:52:43 【问题描述】:我想制作一个可以从 Matlab 调用的 mex 程序,用户可以在其中注册一个 Matlab 函数用于处理。然后程序将使用此函数在后台处理来自另一个程序的数据。 mex 程序和外部程序之间的通信是通过一个共享的全局缓冲区进行的,我使用互斥锁来跟踪它。这部分实际上似乎有效。问题是 Matlab 是单线程的,我想在后台处理数据,以便用户可以继续使用 Matlab。由于 Matlab 是单线程的,我的解决方案是创建一个新线程并从中启动 Matlab 引擎。为此,我需要从从 Matlab 调用的 mex 文件中调用 Matlab 引擎。当我尝试这样做时,程序构建正常,但是当我尝试打开一个新引擎时,Matlab 崩溃。使用下面的测试示例,如果我用test('process2')
Matlab 调用程序(从 Matlab 内部),并且当我使用 ctrl-c Matlab 时会崩溃。使用test('process')
有时似乎可行,但可能会在十次调用之一中使 Matlab 崩溃。
#include "mex.h"
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <stdlib.h>
#include <matrix.h>
#include <unistd.h>
#include "engine.h"
void* local_process(void *arg)
Engine *engine;
engine = engOpen(NULL);
engClose(engine);
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
if ( (nrhs<1) || (! mxIsChar(prhs[0])) )
mexErrMsgTxt("First argument should be a command (string)");
return;
/* Read command string */
int buflen = mxGetNumberOfElements(prhs[0])+1;
char* buf = mxCalloc(buflen, sizeof(char));
if (mxGetString(prhs[0], buf, buflen) != 0)
mexErrMsgTxt("Could not read command string");
mexPrintf("Command: %s\n",buf);
if (strcmp(buf,"process")==0)
pthread_t thread;
pthread_create(&thread,NULL,local_process,NULL);
else if (strcmp(buf,"process2")==0)
Engine *engine;
engine = engOpen(NULL);
engClose(engine);
【问题讨论】:
我认为this link 或其中一些Thread safety of Matlab engine API。这听起来像是进程而不是线程是要走的路。 这两个链接中的问题是多线程问题,即从多个线程访问 Matlab 引擎或 Matlab 函数。在我上面的示例中,每个引擎只能由一个线程访问,但它仍然不起作用。 只是一个想法。您是否尝试过调用任何内置的 Matlab 工具进行多线程处理?例如,batch
命令,或启动timer
,您可以在其中定期运行回调函数。
我希望 Matlab 在外部可用时处理数据,因此我不能使用计时器。使用 Parallel Computing Toolbox(哪个批次是其中的一部分)值得一试,但如果可能的话,我想避免依赖它。
【参考方案1】:
如果它仍然是一个问题,我编译你的代码没有线程部分(只有 "process2" 情况)没有错误,没有停顿,没有问题。 即
#include <mex.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <matrix.h>
#include <engine.h>
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
if ( (nrhs<1) || (! mxIsChar(prhs[0])) )
mexErrMsgTxt("First argument should be a command (string)");
return;
/* Read command string */
int buflen = mxGetNumberOfElements(prhs[0])+1;
char* buf = (char*)mxCalloc(buflen, sizeof(char));
if (mxGetString(prhs[0], buf, buflen) != 0)
mexErrMsgTxt("Could not read command string");
mexPrintf("Command: %s\n",buf);
Engine *engine;
engine = engOpen(NULL);
engClose(engine);
运行良好。我在一台装有 Visual Studio 2010 的 Windows 机器上。
尽管如此,通过 mex 处理 Matlab 引擎显然有一些特殊性。在此链接上,您可以找到我最近遇到的类似案例以及解决方法: http://www.mathworks.com/matlabcentral/newsreader/view_thread/327157#898916
【讨论】:
以上是关于如何在从 Matlab 调用的 mex 函数中使用 Matlab 引擎的主要内容,如果未能解决你的问题,请参考以下文章