有谁知道matlab mex库生命周期是什么?具体来说,我对以下内容感兴趣:
我在这里和网上进行了广泛的搜索,但我找不到这些问题的答案。我的问题在初始化时有一些性能成本,我想尽可能避免这种情况,而不需要编写服务。
答案 0 :(得分:9)
MEX文件保持加载状态,直到您清除它(clear myMexFun
或clear mex
)或退出MATLAB。
对于预加载,我所能建议的是在没有输入或具有nop等效输入的情况下调用该函数。我在mexFunction
中创建了简单的代码路径来处理此类调用而没有错误,最简单的示例是if(!nrhs) return;
。后续调用不需要从磁盘(或MEX函数调用的共享库中的任何其他函数)加载mexFunction
,之后您无需担心初始化成本。
关于初始化/清理,构造函数/析构函数等。在加载或卸载MEX文件时,我不知道有什么方法可以看到 MATLAB正在做什么,但MEX文件是常规共享库(即DLL / SO)只导出单个函数(mexFunction
is the only entry point),因此,正如Amro所指出的,您可以在Windows中实现DllMain
来定义模块和线程附加/分离操作(请参阅his answer)中的优秀例子。我不知道有任何其他与库交互的机制。
要在模块卸载时执行任务,您可以使用mexFunction
中的mexAtExit
向MATLAB注册一个函数,以便在MEX函数卸载时再次调用(再次,清除或MATLAB退出)。只需在全局命名空间中定义static
函数,并将其注册到mexAtExit
。 MATLAB(mexatexit.c)提供的示例演示了关闭在mexFunction
内打开但未关闭的文件流。您还可以释放持久性内存,关闭流等。这是一个人为的例子:
<强> mexDLLtext.cpp 强>:
#include "mex.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
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
)会发生什么变化very well documented,所以我想这不是你的意思询问。
关于多个实例,您可以尝试使用Sysinternals' Process Explorer(如果使用Window)来查看已加载的模块在MATLAB.exe下运行的线程。我只在线程列表中看到一个(单线程)MEX文件的实例,无论我调用该函数多少次或多快。但是,一旦返回命令行,您可以version -modules
查看已加载模块的列表,正如Amro建议的那样。 MEX文件仍然存在,并且与Process Explorer可见的线程列表一样,我只看到MEX某个文件的一个实例。
谢谢,Amro的意见。我很想看到这些问题的一些更权威的答案!
答案 1 :(得分:7)
正如我在评论中提到的,在Windows中,您可以实现DllMain
入口点。这是因为MEX文件只是具有不同扩展名的常规DLL文件。这是一个最小的例子:
#include "mex.h"
#include <windows.h>
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