Matlab-Mex库生命周期
Matlab Mex library lifecycle
有人知道什么是matlab mex库的生命周期吗?具体来说,我对以下内容感兴趣:
- 有没有一种方法可以在调用库之前强制加载它
- 库是单实例还是加载了多个实例
- 在调用之前是否有任何用于初始化的挂钩
- 在卸载库进行清理时,是否有可以截获的析构函数挂钩/信号
我在这里和网上进行了广泛的搜索,但我找不到这些问题的答案。我的问题在初始化方面有一些性能成本,如果可能的话,我希望避免这种情况,而不需要编写服务。
MEX文件将保持加载状态,直到清除它(clear myMexFun
或clear mex
)或退出MATLAB。
对于预加载,我所能建议的就是在没有输入或具有nop等效输入的情况下调用函数。我在mexFunction
中创建了简单的代码路径来处理此类调用而不会出错,最简单的例子是if(!nrhs) return;
。后续调用将不需要从磁盘加载mexFunction
(或MEX函数调用的共享库中的任何其他函数),此后也不需要担心初始化成本。
关于初始化/清理、构造函数/析构函数等。我不知道在加载或卸载MEX文件时,有任何方法可以看到MATLAB在做什么,但MEX文件是一个常规共享库(即DLL/SO),它只导出一个函数(mexFunction
是唯一的入口点),所以,正如Amro所指出的,您可以在Windows中实现DllMain
来定义模块和线程附加/分离操作(请参阅他的回答中的优秀示例)。我不知道有任何其他与图书馆互动的机制。
要在模块卸载时执行任务,可以使用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
)会发生什么,这一点已经有了很好的记录,所以我想这不是你所问的。
关于多个实例,您可以尝试使用Sysinternals的Process Explorer(如果使用Window)来查看哪些加载的模块有在MATLAB.exe下运行的线程。无论我调用函数多少次或多快,我在线程列表中只看到一个(单线程)MEX文件的实例。但是,回到命令行后,您可以按照Amro的建议执行version -modules
以查看已加载模块的列表。MEX文件仍将存在,与Process Explorer可见的线程列表一样,我只看到MEX特定文件的一个实例。
谢谢Amro的意见。我很想看看这些问题的更权威的答案!
正如我在评论中提到的,在Windows中可以实现DllMain
入口点。这是因为MEX文件只是具有不同扩展名的常规DLL文件。这里有一个最小的例子:
testDLL.cpp
#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%xn", hModule);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
mexPrintf("DLL_PROCESS_DETACH: hModule=0x%xn", hModule);
break;
}
return TRUE;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mexPrintf("Inside MEX-functionn");
}
以下是它的工作原理:
>> mex -largeArrayDims testDLL.cpp
>> testDLL
DLL_PROCESS_ATTACH: hModule=0xa0980000
Inside MEX-function
>> testDLL
Inside MEX-function
>> clear testDLL
DLL_PROCESS_DETACH: hModule=0xa0980000
- 如何在共享库的整个生命周期内存储数据
- 如何理解句子的生命周期始于对e的评估
- 它解决了什么问题,对于非真空初始化,生命周期在初始化之前就开始了
- Go/C++gRPC客户端通道和存根生命周期
- 如何将"this"的生命周期移动到C++中的另一个对象中?
- 是否可以通过使用移动/交换 c++11 来延长返回的临时变量的生命周期
- 使用对象的生命周期作为设置器的安全性
- 临时人员的生命周期传递给函数
- 我想知道在构造函数中初始化变量时的生命周期
- Lua 用户数据生命周期管理
- 如何使用 epoll(void* event.data.ptr) 管理 Connection 的生命周期
- C++引用的生命周期
- 在堆栈上有一个对象,而不是在函数的整个生命周期内
- 在 Boost ASIO 服务器中处理生命周期
- C++ lambda 生命周期
- 使用互斥锁跟踪另一个应用的生命周期
- QSharedPointer 或 std::shared_ptr 的生命周期
- 来自async_resolve的 boost::asio::ip::tcp::resolver::iterator 的生命周期是多久?
- 如何调整属于类的唯一指针的字符数组的大小.它必须在程序的整个生命周期中保持活力
- 延长 std::tuple<int&,int> 的生命周期,方法是将其分配给 const std::tuple<int, int>&