我有一个DLP试剂盒,其我需要使用C ++ API经由MATLAB来控制。
说,我用C / C ++为函数/方法{load_data, load_settings,display_data}
在MEX文件名为dlp_controller.cpp / .C。
我知道我可以调用dlp_controller();
与MATLAB。
有没有一种方法,我可以直接调用这个MEX的方法从MATLAB?
说我dlp_controller.cpp MEX看起来:
class dlp{ ... }
dlp::dlp{ ... }
dlp::load_data{ ... }
dlp::load_settings{ ... }
dlp::display_data{ ... }
void mexFunction(int nlhs, mxArray *[],int nrhs, const mxArray *prhs[]{ ... }
我能以某种方式调用像方法dlp_controller.load_data
从MATLAB? 注:一种解决方法可以发送变量dlp_controller
并调用内部使用功能和传递的数据。
据我所知,有这样做没有简单的方法,因为mexFunction
接口是相当平坦 。 不过,也有一些不同的解决方法,我能想到的,应该让你接近。 选择根据您的需要最好的之一。
最简单的是创建一个全局实例dlp
在MEX功能类。 使MEX函数的第一个参数调用指示其全局对象的成员函数被调用的字符串。 最明显的缺点是,你已经把你的MEX函数到一个单例。
如果你需要一个以上的dlp
例如,您可以创建在MEX功能,一些全球集装箱std::map<std::string, dlp>
例如,然后是指每个dlp
一些名字从内部MATLAB实例。 例如,创建一个新的实例,你会调用MEX函数与不已经在存在一个名称map
。 然后,你可以调用MEX函数与此名称,一个字符串,指示调用哪个成员函数,任何参数传递给成员函数。 还设置了一些约定,通过它可以删除一个dlp
从实例map
。
第二个解决方案类似,而不是命名dlp
情况下,你可以返回的句柄到每个实例。 例如,创建一个全球性std::set<dlp *>
当你有MEX函数创建一个新的dlp
实例,将其添加到set
,并在该指针的拷贝到所分配的对象返回到MATLAB(坚持下去类型的标量变量mxUINT64_CLASS
)。 后续调用来调用成员函数对象将这个句柄变量传递给从MATLAB的MEX功能,你会适当的MEX文件中投它时,发现它的内在set
并调用成员函数。
这些方法都不是特别漂亮,但这些是唯一的方法,我知道的调用C ++类的成员函数从MEX文件中。
你可能想看看这份提交给MATLAB中心。 据我所知,它演示的最佳实践,与新闻组的建议许多包括MathWorkers发展。
http://www.mathworks.co.uk/matlabcentral/fileexchange/38964-example-matlab-class-wrapper-for-a-c++-class
最简单的是设计一个MEX包装,保持类对象的实例,并派遣到MEX二进制的呼叫。 我已经做了图书馆对那些试图开发C ++中的MEX包装。
https://github.com/kyamagu/mexplus
这里是一个快速片段。
// C++ class to be wrapped.
class Database;
// Instance session storage.
template class mexplus::Session<Database>;
// Constructor.
MEX_DEFINE(new) (int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) {
InputArguments input(nrhs, prhs, 1);
OutputArguments output(nlhs, plhs, 1);
output.set(0, Session<Database>::create(
new Database(input.get<std::string>(0))));
}
// Destructor.
MEX_DEFINE(delete) (int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) {
InputArguments input(nrhs, prhs, 1);
OutputArguments output(nlhs, plhs, 0);
Session<Database>::destroy(input.get(0));
}
// Member method.
MEX_DEFINE(query) (int nlhs, mxArray* plhs[],
int nrhs, const mxArray* prhs[]) {
InputArguments input(nrhs, prhs, 2);
OutputArguments output(nlhs, plhs, 1);
const Database& database = Session<Database>::getConst(input.get(0));
output.set(0, database.query(input.get<string>(1)));
}
// And so on...
MEX_DISPATCH
对于它的价值,这是我拿的问题。 请参阅在例如MEX文件和类包装这GitHub库 。 这是我想出了一小会儿前一个解决方案,我刚才发现了这个问题,而各具特色的回答一个相关的问题 。 希望这会有所帮助的人。
设计目标
- 管理一个C的多个持久实例++类
- 连续小整数手柄在使用MATLAB(不投三分球)
- 透明地处理资源管理(即MATLAB从来不是分配给C ++类的内存负责):
- 没有内存泄漏,如果MATLAB未能发出“删除”操作。
- 自动释放,如果MEX文件过早地卸载。
- 防止过早卸载模块卫队
- 手柄的有效性,不检查一个神奇的数字隐含验证
- 没有包装类或模仿mexFunction功能,只是在mexFunction一个直观的switch-case块。
需要注意的是,这些目标应该不考虑任何MATLAB类中acheved,但也可以有助于解决内存管理问题。 这样,所得到的MEX文件可以安全地直接使用(但不是太优雅)。
实施概述
对于你的C ++类, class_type
的mexFunction
使用静态数据存储空间来保存持久(调用之间mexFunction
整数手柄和智能指针)表来动态分配的类实例。 一个std::map
被用于此目的,这有利于查找已知的把手,为此类的唯一有效的情况下,保证存在:
typedef unsigned int handle_type;
std::map<handle_type, std::shared_ptr<class_type>>
甲std::shared_ptr
当或者(1)的表元素通过“删除”动作,或者(2)MEX-文件被卸载擦除照顾解除分配的。
为了防止MEX文件,从而MATLAB类的实例存在卸载, mexLock
被称为每次创建一个新的C ++类实例的时间,增加了MEX文件的锁计数。 每一个C ++实例被删除时mexUnlock
被调用时,除去锁计数一个锁。
使用
- [在的.cpp]枚举不同的动作在动作枚举(例如新建,删除,插入等)。 对于每一个枚举动作,指定一个字符串(如“新”,“删除”,“插入”等)作为第一个参数,以MATLAB中的MEX函数传递。
- [在的.cpp]自定义处理用于在体内的switch语句的每个动作
mexFunction
(例如调用相关的C ++类的方法)。 - [在.M](可选)创建,从派生的类cppclass ,创造你的类所需的操作简单的方法。
要求
现代编译器下面的C ++ 11周的特点:
-
shared_ptr
-
auto
-
enum class
-
initializer_list
(为const map
初始化)
的Visual Studio 2013,最近的GCC(可能具有-std=c++11
),并自锵3.1。
资源
- C ++组分(class_wrapper_template.cpp) (
mexFunction
和实例地图)。 重命名和编辑此为++,你要管理的温度。 - 基类(cppclass.m)用于通过MEX文件管理的单个实例
另类设计,清洁的使用情况在这里,是定义一个单独的类以init,fcnA,fcnB,fcnC,... ...方法等,与相应的轻型包装..然后调用来自墨西哥的包装。
如
class A {
public:
A getInstance() {
if ( !instance )
instance = new A(...);
return instance;
}
void fcnA(T1 a1, T2 a2) {
//yada yada
}
private:
static A* instance;
};
A::instance = NULL;
//begin wrappers for marshalling to class method
A* getInstance( ) {
return A::getInstance();
}
void fcnA(T1 a1, T2 a2) {
getInstance()->fcnA(a1,a2);
}
//ad nauseum