Matlab Mex库生命周期

有谁知道matlab mex库的生命周期是什么? 具体来说,我对以下内容感兴趣:

  1. 有没有办法在调用它之前强制加载库?
  2. 库是单例还是多个实例加载?
  3. 在调用之前是否有任何挂钩用于初始化?
  4. 是否有一个析构函数钩子/信号,可以在卸载库进行清理时截获?

我在这里和网上进行了广泛的搜索,但我找不到这些问题的答案。 我的问题在初始化时有一些性能成本,我想尽可能避免这种情况,而无需编写服务。

正如我在评论中提到的,在Windows中你可以实现DllMain入口点。 这是因为MEX文件只是具有不同扩展名的常规DLL文件。 这是一个最小的例子:

testDLL.cpp

 #include "mex.h" #include  BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { switch (dwReason) { case DLL_PROCESS_ATTACH: mexPrintf("DLL_PROCESS_ATTACH: hModule=0x%x\n", hModule); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: mexPrintf("DLL_PROCESS_DETACH: hModule=0x%x\n", hModule); break; } return TRUE; } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { mexPrintf("Inside MEX-function\n"); } 

下面是它的工作原理:

 >> mex -largeArrayDims testDLL.cpp >> testDLL DLL_PROCESS_ATTACH: hModule=0xa0980000 Inside MEX-function >> testDLL Inside MEX-function >> clear testDLL DLL_PROCESS_DETACH: hModule=0xa0980000 

MEX文件保持加载状态,直到您清除它( clear myMexFunclear mex )或退出MATLAB。

对于预加载,我所能建议的是调用没有输入或具有nop等效输入的函数。 我在mexFunction创建了简单的代码路径来处理这样的调用而没有错误,最简单的例子是if(!nrhs) return; 。 后续调用不需要从磁盘(或MEX函数调用的共享库中的任何其他函数)加载mexFunction ,之后您无需担心初始化成本。

关于初始化/清理,构造函数/析构函数等。我不知道在加载或卸载MEX文件时有什么方法可以看到MATLAB正在做什么 ,但是MEX文件是一个只导出的常规共享库(即DLL / SO)单个函数( mexFunction是唯一的入口点 ),因此,正如Amro所指出的,您可以在Windows中实现DllMain来定义模块和线程附加/分离操作(请参阅他的答案中的优秀示例)。 我不知道有任何其他与库交互的机制。

要在模块卸载时执行任务,可以在mexFunction使用mexAtExit向MATLAB注册一个函数,以便在MEX函数卸载时再次调用(再次,清除或MATLAB退出)。 只需在全局命名空间中定义static函数,并将其注册到mexAtExit 。 MATLAB(mexatexit.c)提供的示例演示了关闭在mexFunction中打开mexFunction关闭的文件流。 你也可以释放持久性内存,关闭流等。这是一个人为的例子:

mexDLLtext.cpp

 #include "mex.h" #include  #include  #include  static FILE *fp=NULL; static double *pDataC=NULL, *pDataCpp=NULL, *pMxData=NULL; static char fName[L_tmpnam], counter = 0; static void CleanUp(void) { fclose(fp); /* close file opened with fopen */ free(pDataC); /* deallocate buffer allocated with malloc/calloc */ delete[] pDataCpp; /* deallocate buffer allocated with new double[...] */ mxFree(pMxData); /* free data created with mx function like mxMalloc */ mexPrintf("Closing %s and freeing memory...\n",fName); } void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (!fp) { tmpnam(fName); fp = fopen(fName,"w"); } fprintf(fp,"%d ",++counter); if (!pDataC) pDataC = (double*) malloc(sizeof(double)*16); if (!pDataCpp) pDataCpp = new double[16]; if (!pMxData) { pMxData = (double*) mxMalloc(sizeof(double)*16); mexMakeMemoryPersistent(pMxData); mexPrintf("First!\n"); } mexAtExit(CleanUp); // Then use the persistent data... } 

运行时:

 >> mex -largeArrayDims mexDLLtest.cpp >> for i=1:5, mexDLLtest; end First! >> clear mexDLLtest Closing \s1rg.1 and freeing memory... >> type E:\s1rg.1 1 2 3 4 5 

并且您可以通过mexLockmexUnlock控制文件的卸载。

当函数启动并返回MATLAB时,参数(即prhsplhs )会发生什么prhs ,另一方面,我猜这不是你所要求的。

关于多个实例,您可以尝试使用Sysinternals的Process Explorer (如果使用Window)来查看已加载的模块在MATLAB.exe下运行的线程。 我只在线程列表中看到一个 (单线程)MEX文件的实例 ,无论我调用该函数多少次或多快。 但是,一旦返回命令行,您可以执行version -modules以查看已加载模块的列表,如Amro所建议的那样。 MEX文件仍然存在,并且与Process Explorer可见的线程列表一样,我只看到MEX某个文件的一个实例。

谢谢,Amro的意见。 我很想看到这些问题的更权威的答案!