Matlab Mex库生命周期

时间:2013-12-13 21:03:49

标签: c++ c matlab mex

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

  1. 有没有办法在调用它之前强制加载库?
  2. 库是单例还是多个实例加载?
  3. 在调用之前是否有任何挂钩用于初始化?
  4. 卸载库以进行清理时是否有可以拦截的析构函数挂钩/信号?
  5. 我在这里和网上进行了广泛的搜索,但我找不到这些问题的答案。我的问题在初始化时有一些性能成本,我想尽可能避免这种情况,而不需要编写服务。

2 个答案:

答案 0 :(得分:9)

MEX文件保持加载状态,直到您清除它(clear myMexFunclear 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 

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

当函数启动并返回MATLAB时,参数(即prhsplhs)会发生什么变化very well documented,所以我想这不是你的意思询问。

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

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

答案 1 :(得分:7)

正如我在评论中提到的,在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%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