Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MATLAB no longer unloading MEX-files after upgrade to macOS Mojave

In MATLAB, clear mex unloads all MEX-files from memory (unless they're locked). Under previous versions of macOS, I was able to re-compile a MEX-file and run the modified version without restarting MATLAB, simply by issuing a clear mex command. This is no longer possible under Mojave.

For example, take this trivial MEX-file (get_data_pointer.c):

#include "mex.h"

void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] )
{
  plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
  *(uint64_t*)mxGetData(plhs[0]) = (uint64_t)mxGetData(prhs[0]);
}

We can create the MEX-file and load it in memory with

mex get_data_pointer.c
get_data_pointer(0)

To clear it,

clear mex
[~,mexfiles] = inmem
version -modules

inmem indeed returns an empty cell array indicating no MEX-files are loaded in memory, But version -modules (undocumented, from this answer) still shows /Users/cris/matlab/get_data_pointer.mexmaci64 in its output. And changing the MEX-file source code and re-compiling demonstrates that, indeed, the MEX-file is never reloaded, the old version is still being run until one exits MATLAB.

I am seeing this on MATLAB R2017a on macOS Mojave. This was never a problem with the same MATLAB version under High Sierra.

How can I force MATLAB to unload the MEX-file without restarting?

like image 377
Cris Luengo Avatar asked Dec 20 '25 11:12

Cris Luengo


1 Answers

This doesn't technically solve the problem rather than work around it, but I have been using this compilation model because of the problem you mentioned I think. With this workflow I am able to compile Mex files as many times as needed and the version called is always the latest. It works as follows:

  • Say you want to compile a Mex file to be callable in the current working directory.
  • Keep your C++ source Mex files in a subfolder mex/ (not on the path). Say the file you want to compile is mex/mex_function.cpp.
  • The scripts below will create a bin/ folder if it doesn't exist, and "reserve" a temporary filename bin/mex_function_<timestamp>.<mexext> to be used as the compilation output.
  • It will also symlink the local file mex_function.<mexext> to the temporary file reserved in bin/, and update that link every time a new compilation is run.
  • It does NOT run the compilation step for you though, you need to put together the mex() command yourself to actually create the temporary compiled file in bin/.

Please don't take this script as-is; take it as guidance and adapt it for your needs. I personally have my own wrapper around mex() to create the compilation command and set all options / compiler flags as needed — you might have something similar on your side.

function outname = matlabBugWorkaround_compile( folder, name )
%
% The input folder is expected to have two subfolders:
%   bin/ will contain temporary compiled Mex files
%   mex/ contains the source Mex files
%   
% The compilation model works as follows:
%   1. reserve filename in bin/ subfolder for temporary Mex file, using datestr suffix
%   2. create a symbolic link in input folder to reserved temporary Mex file
%   3. call mex() to compile the source file in mex/ and save the output in bin/
%
% This function takes care of steps 1 and 2, and returns the name of the temporary Mex 
% file in bin/, which does not exist until the Mex file is actually compiled.
%
% .
% ├── bin/mex_function_240824-105633.mexmaci64
% ├── mex/mex_function.cpp
% └── mex_function.mexmaci64 -> bin/mex_function_240824-105633.mexmaci64
%
%
% Practically speaking:
%   - put C++ Mex files in mex/ subfolder
%   - call this function to create a symlink to a temporary compiled Mex file in bin/,
%     which does not exist yet
%   - run mex() taking the C++ file in mex/ as an input, using option "-output" with 
%     the filename returned by this function, and using option "-outdir" with the bin/
%     subfolder
%

    % binary folder is where the Mex output will be saved
    bindir = fullfile(folder,'bin');
    if ~isfolder(bindir)
        assert( mkdir(bindir)==1, 'Could not create folder: %s', bindir );
    end

    % use timestamp to create unique name for temporary Mex file
    ext = ['.' mexext];
    stamp = datestr(now,'yymmdd-HHMMSS');
    outname = [name '_' stamp ext];

    % remove other binaries with the same prefix 
    torem = dir(fullfile( bindir, [name '_*'] ));
    for i = 1:length(torem)
        file = torem(i);
        delete(fullfile(file.folder,file.name));
    end

    % create symlink
    mexlink = fullfile( folder, [name ext] );
    if isfile(mexlink)
        delete(mexlink); 
    end
    unix(['ln -s "' fullfile('bin',outname) '" "' mexlink '"']);

end

I hope this helps, happy to answer questions about it. Again sorry this doesn't actually solve the problem, it's just a workaround.

like image 159
Jonathan H Avatar answered Dec 22 '25 03:12

Jonathan H



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!