在您清除(clear myMexFun或clear mex)或退出MATLAB 之前,MEX文件将保持加载状态.
对于预加载,我所能建议的是调用没有输入或具有nop等效输入的函数.我已经在我的mexFunctions中创建了简单的代码路径来处理这样的调用而没有错误,最简单的例子是if(!nrhs) return;.后续调用不需要加载mexFunction磁盘(或MEX函数调用的共享库中的任何其他函数),之后您不必担心初始化成本.
关于初始化/清理,构造函数/析构函数等.我不知道有什么方法可以看到MATLAB在加载或卸载MEX文件时正在做什么,但MEX文件是一个常规的共享库(即DLL/SO),它只是导出单个函数(mexFunction是唯一的入口点),因此,正如Amro所指出的,您可以DllMain在Windows中实现一个定义模块和线程附加/分离操作(请参阅他的答案中的优秀示例).我不知道有任何其他与库交互的机制.
要在模块卸载时执行任务,您可以使用mexAtExit内部mexFunction向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...
}
Run Code Online (Sandbox Code Playgroud)
运行时:
>> 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
Run Code Online (Sandbox Code Playgroud)
发生了什么参数(即prhs,plhs)当函数开始,并返回到MATLAB是非常有据可查的,而另一方面,所以我想这不是你问什么.
关于多个实例,您可以尝试使用Sysinternals的Process Explorer(如果使用Window)来查看已加载的模块在MATLAB.exe下运行的线程.我只在线程列表中看到一个(单线程)MEX文件的实例,无论我调用该函数多少次或多快.但是,一旦回到命令行,您就可以version -modules查看已加载模块的列表,正如Amro建议的那样.MEX文件仍然存在,并且与Process Explorer可见的线程列表一样,我只看到MEX某个文件的一个实例.
谢谢,Amro的意见.我很想看到这些问题的一些更权威的答案!
正如我在评论中提到的,在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");
}
Run Code Online (Sandbox Code Playgroud)
下面是它的工作原理:
>> mex -largeArrayDims testDLL.cpp
>> testDLL
DLL_PROCESS_ATTACH: hModule=0xa0980000
Inside MEX-function
>> testDLL
Inside MEX-function
>> clear testDLL
DLL_PROCESS_DETACH: hModule=0xa0980000
Run Code Online (Sandbox Code Playgroud)