Matlab Mex库生命周期
有谁知道matlab mex库的生命周期是什么? 具体来说,我对以下内容感兴趣:
- 有没有办法在调用它之前强制加载库?
- 库是单例还是多个实例加载?
- 在调用之前是否有任何挂钩用于初始化?
- 是否有一个析构函数钩子/信号,可以在卸载库进行清理时截获?
我在这里和网上进行了广泛的搜索,但我找不到这些问题的答案。 我的问题在初始化时有一些性能成本,我想尽可能避免这种情况,而无需编写服务。
正如我在评论中提到的,在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 myMexFun
或clear 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
并且您可以通过mexLock
和mexUnlock
控制文件的卸载。
当函数启动并返回MATLAB时,参数(即prhs
, plhs
)会发生什么prhs
,另一方面,我猜这不是你所要求的。
关于多个实例,您可以尝试使用Sysinternals的Process Explorer (如果使用Window)来查看已加载的模块在MATLAB.exe下运行的线程。 我只在线程列表中看到一个 (单线程)MEX文件的实例 ,无论我调用该函数多少次或多快。 但是,一旦返回命令行,您可以执行version -modules
以查看已加载模块的列表,如Amro所建议的那样。 MEX文件仍然存在,并且与Process Explorer可见的线程列表一样,我只看到MEX某个文件的一个实例。
谢谢,Amro的意见。 我很想看到这些问题的更权威的答案!