Mex function does not update after recompilation

I have a simple mex function that calls another C ++ function from the library. I will compile the source with

mex -cxx mymexfunction.cpp -I/some/include -L/some/lib -lmylib 

The mylib library is dynamic (.so) and linked to some other libraries (boost, OpenCV, and a few more).

The problem I encountered is that once I called the mymexfunction function once, it will not be updated when recompiling the source code. I tried

 clear clear all clear mex clear functions clear fun('mymexfunction') munlock('mymexfunction') unloadlibrary('mymexfunction') 

... but nothing helps! I have to restart Matlab in order to be able to see the updated mexfunction. Even if I delete the compiled mex file and recompile, I still get the old version of the mex function (not on disk, but in memory).

Everything is fine if I do not contact mylib, but I do not know what could be the culprit, which prevents the update. The library, unfortunately, is too large and too interwoven to remove individual modules one at a time.

Are there any known conditions that can cause such problems?

Clarification:

I am only updating the contents of the mex function, not the library.

Update:

It works under Ubuntu 11.04 with Matlab R2011a! I tried to reproduce the same environment on my OpenSUSE machine (R2011a, Boost 1.42, OpenCV 2.2 is dynamically connected, ...), but still no luck. Therefore, I came to the conclusion that there is nothing wrong with my library (otherwise it will not work under Ubuntu), but this should be some clash of dependencies and internal Matlab libraries. I'm officially giving up. Praetorian and Amro, thanks for your help!

+6
source share
2 answers

The mex command automatically clears the mex function if it is currently loaded into memory. Are you sure your mex function closes any descriptor it holds in another library? If such a descriptor exists, this may prevent the OS from unloading the mex file.

I used the following set of commands to clear mex functions manually, and in my experience, using the full path to the mex file when calling clear . So give it a try, and if it still doesn't get unloaded, you can start looking at the code to load and unload another library.

 [~,f] = inmem( '-completenames' ); result = strfind( f, ['mymexfile' '.' mexext] ); result = f(cellfun( @isempty, result, 'UniformOutput', true ) == 0); clear( result{:} ) 

Try the inmem command again after the above and see if your mex file is listed.

Something that can help you make sure another library is unloaded might use std::shared_ptr to store the handle to that library. Then, at the beginning of the mexFunction() entry point, load the library and paste the handle into shared_ptr . shared_ptr will also need to use a custom delete file to unload the library (on Windows, the user manager will call FreeLibrary ).

Of course, if this is caused by an error in another library, none of this will help.

+4
source

Trying to reproduce the problem, I wrote a minimal working example for your case: a MEX file that refers to a dynamic library and uses one of its public functions. I tested the following on 32-bit WinXP, using MATLAB R2010b with VS2010 as a compiler (for DLL and MEX).

The example simply adds floating point numbers. The MEX file accepts matrices / vectors and loops over the elements that call the add() function from the library on each pair.

Adder.h

 #ifndef ADDER_H #define ADDER_H #ifdef __cplusplus extern "C" { #endif #ifdef _WIN32 # ifdef BUILDING_DLL # define DLL_IMPORT_EXPORT __declspec(dllexport) # else # define DLL_IMPORT_EXPORT __declspec(dllimport) # endif #else # define DLL_IMPORT_EXPORT #endif DLL_IMPORT_EXPORT double add(double x, double y); #ifdef __cplusplus } #endif #endif 

Adder.c

 #include "Adder.h" double add(double x, double y) { return x+y; } 

mymexfunction.c

 #include "mex.h" #include "Adder.h" #define X_IN input[0] #define Y_IN input[1] #define Z_OUT output[0] void mexFunction(int output_size, mxArray *output[], int input_size, const mxArray *input[]) { double *inX, *inY, *outZ; mwSize m,n; int i; /* check for proper number of arguments */ if (input_size != 2) { mexErrMsgTxt("Two input arguments required."); } if (output_size > 1) { mexErrMsgTxt("Too many output arguments."); } /* check input argument sizes */ m = mxGetM(X_IN); n = mxGetN(X_IN); if ( !mxIsDouble(X_IN) || !mxIsDouble(Y_IN) ) { mexErrMsgTxt("Input arguments must be matrices/vectors of doubles."); } if ( mxGetM(Y_IN)!=m || mxGetN(Y_IN)!=n ) { mexErrMsgTxt("X and Y must be of same size."); } /* Create a matrix for the return argument */ Z_OUT = mxCreateDoubleMatrix(m, n, mxREAL); // get pointers to data inX = (double *) mxGetPr(X_IN); inY = (double *) mxGetPr(Y_IN); outZ = (double *) mxGetPr(Z_OUT); // compute and store result for(i=0; i<m*n; ++i) { outZ[i] = add(inX[i], inY[i]); } return; } 

First we create a dynamic library, as I mentioned that I use VC ++ for the job. On Unix based systems with GCC, I think this step will be similar (correct me if I am wrong):

 gcc -c -DBUILDING_DLL Adder.c -o Adder.o -I. gcc -shared -o libAdder.so Adder.o -Wl,--out-implib,libAdder.a 

then in MATLAB we will compile the MEX file:

 >> mex mymexfunction.c -I. -L. -lAdder 

(Note: I put everything in one folder to avoid path issues.)

Next, we can check the function in MATLAB:

 >> mymexfunction([1 2;3 4], [5 6; 7 8]) ans = 6 8 10 12 

Using the Process Explorer tool from Sysinternals, we can view loaded DLLs using the MATLAB process, the MEX function, and our custom dynamic library

sysinternals

If we select the clear mex command, then both modules will be unloaded as expected (which is checked using the Process Explorer). This is also confirmed by INMEM as @Praetorian :

 clear mex [~,m] = inmem('-completenames'); any( ismember(m,fullfile(pwd,['mymexfunction.' mexext])) ) 

Finally, if we make some changes to mymexfunction.c :

 // add 10 to all results outZ[i] = add(inX[i], inY[i]) + 10.0; 

recompile MEX and check it again (all in the same session, without restarting). The result will reflect the changes you see:

 >> mymexfunction([1 2;3 4], [5 6; 7 8]) ans = 16 18 20 22 

Try repeating the above on a Mac / Linux computer. If you still get the old amounts, then this should be a mistake specific to non-Windows platforms, and it should be reported to MathWorks ... Otherwise, I suspect that there should be some freed resources in your code that remain in memory ?

+3
source

Source: https://habr.com/ru/post/894723/


All Articles