我已经将C ++集成到Matlab中;在我的示例中,有三个简单文件:Matlab脚本main.m
,Matlab类文件myClass.m
和C ++文件myMex.cpp
。
在main.m
中,我叫该类给出一个字符串作为输入。
main.m
:myVar = myClass('test.bin');
myClass.m
:classdef myClass < handle
properties
bitStreamName;
cabac_handle;
end
methods
function obj = myClass(fn)
obj.bitStreamName = fn;
obj.cabac_handle = myMex('First', obj.bitStreamName);
myMex('Second', obj.cabac_handle);
end
end
end
myMex.cpp
:#include "mex.h"
#include <iostream>
using namespace std;
void _main();
class CABAC {
public:
CABAC() {};
~CABAC() {};
char* fn;
};
// the MEX interface function
void mexFunction(
int nlhs, // Number of expected output mxArrays
mxArray *plhs[], // Array of pointers to the expected output mxArrays
int nrhs, // Number of input mxArrays
const mxArray *prhs[] // Array of pointers to the input mxArrays
)
{
CABAC *c; // pointer to (new) instance of the CABAC class
char* fn = 0;
char cmd[64]; // temp char array to hold the command
// start parsing the input command
mxGetString(prhs[0], cmd, sizeof(cmd));
string inputCmd(cmd);
if (inputCmd == "First")
{
// get the filename string
fn = mxArrayToString(prhs[1]);
c = new CABAC;
uintptr_t c_value = (uintptr_t)c;
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
*mxGetPr(plhs[0]) = c_value; // return pointer to matlab environment
c->fn = fn;
mexPrintf("Pointer: %p\n", c);
mexPrintf("Filename: %s\n", c->fn);
}
else if (inputCmd == "Second")
{
uintptr_t my_value = *mxGetPr(prhs[1]);
CABAC *my_pointer = (CABAC *)my_value;
mexPrintf("Pointer: %p\n", my_pointer);
mexPrintf("Filename: %s\n", my_pointer->fn);
}
}
第一次调用myMex.cpp
时,我创建了一个CABAC
类的对象,并将字符串"test.bin"
与其属性fn
关联。最后,指针的值返回到Matlab环境。
第二次,我只是简单地获得了指向先前实例化对象的指针,在这里发生了一些奇怪的事情。特别是,同时打印指针的地址和属性fn
时,前者始终是正确的(即,地址与对象相同),而后者有时是正确的("test.bin"
是印刷),有时是完全随机的错误(出现奇怪的字符串,每次执行都不同)。
要执行我的代码,只需使用以下指令编译main.m
后即可运行myMex.cpp
:
mex CXXFLAGS="\$CXXFLAGS -std=c++11" -g myMex.cpp
或
mex COMPFLAGS="\$CXXFLAGS -std=c++11" -g myMex.cpp
您能帮我了解文件名怎么了吗?
编辑:似乎c
在第一次myMex
调用之后被删除。如何将指向CABAC
对象(及其所有属性)的指针保留在内存中?
答案 0 :(得分:1)
这里有很多问题。首先,您要投射一个指向double
的指针,该指针不会保留其表示形式:
uintptr_t c_value = (uintptr_t)c;
plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
*mxGetPr(plhs[0]) = c_value; // return pointer to matlab environment
相反,创建一个64位整数数组以将指针保存到:
plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
*(uint64_t*)mxGetData(plhs[0]) = (uint64_t)c;
(由于MATLAB R2018a有alternatives to mxGetData
for each type,在这种情况下为mxGetUint64s
)。
第二,当MEX文件被卸载时,可能会删除new
ed的内存。这可以随时发生。为防止这种情况,请使用mexLock
将MEX文件锁定在内存中。为防止内存泄漏,您将需要包含在完成使用后删除内存的代码。由于您的MATLAB类是一个句柄类,因此可以实现。
第三,使用错误的指针调用MEX文件非常容易,这很可能会使整个MATLAB崩溃。当前的实现无法解决这个问题。
第四,如Navan所指出,以下行创建了字符串的副本,但在MATLAB维护的内存缓冲区中:
fn = mxArrayToString(prhs[1]);
MATLAB将自动删除mxMalloc
分配的所有内存,并在mexFunction
末尾删除类似的内存。因此,fn
将指向释放的内存。您需要在此处管理的内存中手动创建一个副本。建议您将字符串复制到std::string
中:
class CABAC {
public:
std::string fn;
};
fn = mxArrayToString(prhs[1]); // Will copy the string to `fn`.
但是,我建议使用其他方法:
NULL
指针(例如,用于删除的对象还是用于数组)尚未使用的元素)。您应该知道,在调用MEX文件之间,全局变量将保持不变(只要被锁定)。因此,您将需要一个全局数组(在mexFunction
外部定义)来存储指针。或者,在static
内声明数组mexFunction
。
This MEX-file实现了此处描述的建议,尽管它不是一个简单的例子,但我希望它可以作为一个起点。在此函数中,我使用的是std::map
而不是普通数组来存储句柄。