Жизненный цикл библиотеки Matlab Mex
Кто-нибудь знает, что такое жизненный цикл библиотеки matlab mex? В частности, меня интересует следующее:
- Есть ли способ заставить библиотеку загружаться до ее вызова?
- Является ли библиотека одиночной или загружена несколькими экземплярами?
- Есть ли крючки для инициализации перед вызовом?
- Есть ли крючок/сигнал деструктора, который может быть перехвачен, когда библиотека выгружается для очистки?
Я сделал обширный поиск здесь и в Интернете, и я не мог найти ответы на эти вопросы. Моя проблема связана с некоторыми затратами на инициализацию, и я хотел бы избежать этого, если это возможно, без необходимости писать службу.
Ответы
Ответ 1
Как я уже упоминал в комментариях, в 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
Ответ 2
Файл MEX остается загруженным до тех пор, пока вы его не очистите (clear myMexFun
или clear mex
) или закройте MATLAB.
Для предварительной загрузки все, что я могу предложить, это вызвать функцию без входов или с эквивалентными входами. Я создал простые кодовые пути в моем mexFunction
для обработки таких вызовов без ошибок, самым простым примером является 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...
}
При запуске:
>> 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
.
Что происходит с аргументами (т.е. prhs
, plhs
) при запуске функции и возвращается в MATLAB очень хорошо документировано, с другой стороны, поэтому я думаю, что не то, о чем вы просите.
Что касается нескольких экземпляров, вы можете попробовать использовать Проводник процессов Sysinternals (если использовать Window), чтобы посмотреть, какие загруженные модули имеют потоки работает под MATLAB.exe. Я вижу только один экземпляр (однопоточный) MEX файл в списке нитей независимо от того, сколько раз или как быстро я вызываю функцию. Однако, вернувшись в командной строке, вы можете сделать version -modules
, чтобы увидеть список загруженных модулей, как предложил Амро. Файл MEX все равно будет присутствовать, и, как и в списке потоков, видимых в Process Explorer, я вижу только один экземпляр файла MEX.
Спасибо, Amro для ввода. Мне интересно видеть еще более авторитетные ответы на эти вопросы!