我有一个简单的mex函数,它从库中调用另一个C ++函数。我用
编译源代码mex -cxx mymexfunction.cpp -I/some/include -L/some/lib -lmylib
mylib库是动态的(.so),并且与其他一些库(boost,OpenCV等)相关联。
我遇到的问题是,一旦我调用函数mymexfunction一次,当我重新编译源代码时它将不会更新。我试过了
clear
clear all
clear mex
clear functions
clear fun('mymexfunction')
munlock('mymexfunction')
unloadlibrary('mymexfunction')
......但没有任何帮助!我必须重新启动Matlab才能看到更新的mexfunction。即使我删除已编译的mex文件并重新编译,我仍然会获得旧版本的mex函数(不在磁盘上,但在内存中)。
如果我没有链接到mylib,一切都很好,但我不知道阻止更新的罪魁祸首是什么。遗憾的是,图书馆太大而且交织在一起,无法逐个删除单个模块。
是否存在可能导致此类问题的已知条件?
澄清:
我只更新mex功能的内容,而不是库。
更新
它在Ubuntu 11.04下使用Matlab R2011a工作!我试图在我的OpenSUSE机器上重现相同的环境(R2011a,Boost 1.42,动态链接的OpenCV 2.2 ......)但仍然没有运气。所以我得出结论,我的库没有任何问题(否则它在Ubuntu下不起作用),但它必须是依赖项和Matlab内部库的一些冲突。我正式放弃了。 Praetorian和Amro,谢谢你的帮助!
答案 0 :(得分:4)
mex
命令会自动清除mex函数(如果它当前已加载到内存中)。你确定你的mex函数正在关闭它对其他库的任何句柄吗?如果存在这样的句柄,则可能会阻止操作系统卸载mex文件。
我已经使用以下命令集手动清除mex函数,根据我的经验,在调用clear
时使用mex文件的完整路径。所以尝试一下,如果它仍然没有被卸载,你可能想要开始查看加载和卸载其他库的代码。
[~,f] = inmem( '-completenames' );
result = strfind( f, ['mymexfile' '.' mexext] );
result = f(cellfun( @isempty, result, 'UniformOutput', true ) == 0);
clear( result{:} )
尝试在上面的命令之后再次运行inmem
命令,看看你的mex文件是否仍然列出。
可能有助于确保其他库被卸载的东西可能是使用std::shared_ptr
来保存此库的句柄。然后,在mexFunction()
入口点的开头加载库并将句柄粘贴到shared_ptr
中。 shared_ptr
还需要使用自定义删除工具来卸载库(在Windows上,自定义删除工具会调用FreeLibrary
)。
当然,如果这是由其他库中的错误引起的,这一切都无济于事。
答案 1 :(得分:3)
尝试重现这个问题,我为您的案例编写了一个最小的工作示例:一个链接动态库的MEX文件,并使用其公开的函数之一。我使用MATLAB R2010b和VS2010作为编译器(对于DLL和MEX)在WinXP 32位上测试了以下内容。
该示例仅添加浮点数。 MEX文件接受矩阵/向量,并在每对上从库调用add()
函数的元素上循环。
#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
#include "Adder.h"
double add(double x, double y)
{
return x+y;
}
#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;
}
首先我们构建动态库,正如我所提到的,我正在使用VC ++来完成工作。在使用GCC的基于Unix的系统上,我认为这一步就像(如果我错了,请纠正我):
gcc -c -DBUILDING_DLL Adder.c -o Adder.o -I.
gcc -shared -o libAdder.so Adder.o -Wl,--out-implib,libAdder.a
然后在MATLAB中,我们编译MEX文件:
>> mex mymexfunction.c -I. -L. -lAdder
(注意:我将所有内容放在同一文件夹中以避免处理路径问题。)
接下来,我们可以在MATLAB中测试函数:
>> mymexfunction([1 2;3 4], [5 6; 7 8])
ans =
6 8
10 12
使用Sysinternals的Process Explorer工具,我们可以通过MATLAB过程,MEX函数和我们的自定义动态库查看加载的DLL:
如果我们发出命令clear mex
,则按预期卸载两个模块(使用Process Explorer验证)。 INMEM也证实了这一点,@Praetorian表明:
clear mex
[~,m] = inmem('-completenames');
any( ismember(m,fullfile(pwd,['mymexfunction.' mexext])) )
最后,如果我们对mymexfunction.c
进行一些更改:
// add 10 to all results
outZ[i] = add(inX[i], inY[i]) + 10.0;
重新编译MEX,然后再次测试(全部在同一个会话中,不重启)。结果将反映您所看到的变化:
>> mymexfunction([1 2;3 4], [5 6; 7 8])
ans =
16 18
20 22
请尝试在Mac / Linux计算机上重复上述步骤。如果您仍然收到旧的金额,那么它必须是特定于非Windows平台的错误,并且应该向MathWorks报告...否则我怀疑在您的代码中,必须有一些未释放的资源导致模块留在记忆中?