图片缩略图

示例MATLAB类包装一个c++类

version 1.4.0.0 (8.28 KB) by 奥利弗·伍德福德
这是一个如何通过mex接口安全地将c++类封装在MATLAB类中的例子。
4.9
42评级

29下载

更新08年2月2018年

查看版本历史记录

查看许可协议

编者按:这个文件被选为MATLAB中心推荐商品

这个包提供了一个例子,说明如何通过mex接口安全地将c++类封装到MATLAB类中,而不存在内存泄漏,同时在MATLAB中实现一个类似于底层c++接口的接口。
下载后,电话:
> > run_example
在MATLAB中看一个例子的实现在行动。

看看run_example。M, example_mex.cpp(以及可选的example_interface. cpp)m,如果你不想使用标准接口),看看这是如何实现的,并将结构复制到接口与你自己的c++类。

本次提交的灵感来自以下新闻组线程:
//www.tatmou.com/matlabcentral/newsreader/view_thread/278243
感谢所有做出贡献的人。

引用为

奥利弗·伍德福德(2021)。示例MATLAB类包装一个c++类(//www.tatmou.com/matlabcentral/fileexchange/38964-example-matlab-class-wrapper-for-a-c-class), MATLAB中央文件交换。检索

意见及评分(64

费德里科•Barban

Jean-Sebastien拼

Niraj帕特尔

拉斐尔·舍伊布

蔡昉

嗨,我有个问题。如果我需要多次调用obj.train(),并将不同的参数从matlab传递到obj.train(),该怎么办?谢谢!

阿里·苏拉比

你好,

谢谢你这难以置信的代码。我只是有个问题。你能帮我吗?我想在MATLAB中反复调用我的C++类,每次迭代时,我都会收到一个数据文件。我不知道如何通过使用代码把我的文件名传递给C++类。

谢谢

Vojtech Vrba

布伦特福斯特

玛尔塔Grobelna

Chiheb本Hammouda

一个伟大的代码。然而,当使用它来包装我的c++代码时,我遇到了一个问题,例如使用std::vector!!你是否知道我可以在mex中定义什么类型,以便它可以接受输入或输出定义为std::vector在我的c++代码中?多谢。

汉娜玛丽亚·鲍尔

艾伯特Piek

Josh Sanz

奥利弗·伍德福德

我不知道你是什么意思。类必须被实例化才能使用它们。因此,它提供了c++类实例的接口。这就是它的作用。一个类接口可以用来与该类的所有实例进行接口。

罗伯特。

我有一个问题:我也可以使用它来包装类的实例吗?假设我因为性能原因在c++中创建了一个类的实例,我想把它封装到MATLAB中的一个类的实例中。这可能吗?谢谢。

Mendi

佳艺

这个类接口工作起来很有魅力!但是我发现,如果你创建和删除一个class_interface实例,当你第二次创建和删除时,MATLAB有很大的变化会崩溃。我不知道如何解决这个问题。我尝试过使用和不使用mexLock进行编译。

凯文

劳纳克·博克

伟大的工作!非常感谢这些文件:D

骄傲的朱

阿拉

阳昱

谢谢你的代码。
我正在做背景减法项目,这段代码救了我的命!!!

托马斯Pfeil

曼努埃尔·马林

卓越的贡献。
谢谢奥利。

大卫·范德林

我已经使用这段代码有一段时间了~6个月了。到现在为止,一直都还不错。
然而,今天我发现一些奇怪的行为,为我的代码:

在清除(清除所有)的两个实例是存在的,一个是我创建的,一个是MATLAB在我的代码期间创建的。这个附加对象是在没有调用构造函数的情况下创建的,并且有一个未初始化的句柄,在isValid()上发生崩溃。
我可以想象出两种应对方法:
1)确保句柄已初始化(我不知道这将如何工作)。
2)只在调用构造函数“this = SBTL_fluids(varargin)”时调用“SBTL_fluids_mex('delete', this. objecthandle);”

莫兰x

泽维尔

约瑟夫•

埃里克•约翰逊

这是一个关于如何在MATLAB和c++对象之间创建接口的简单而伟大的示例。

布莱恩·沃马克

很好的例子。

大卫

看起来很有趣,但是当我尝试编译时,我得到了以下错误消息:致命错误C1083:无法打开包含文件:' stint .h':没有这样的文件或目录。

我在网上查阅了一些资料,这是因为我的Visual Studio(2008)版本不支持这个库。金宝app如果Matlab使用visual studio编译,你需要下载这些库来运行,并在编译时添加一个-i参数来告诉文件位置:https://code.google.com/p/msinttypes/downloads/detail?name=msinttypes-r26.zip

中世纪商业行会

乔尔:这似乎是有效的,但我不能评论它是否安全。不过,我也会想象这个指针指向一个静态字符串。试一试。

乔尔·安德森

将class_handle::name_m的类型更改为const char*是否安全?我想象“typeid(base).name()”返回一个指向静态存储对象的指针。

奥利弗·伍德福德

An Tran Lam:类型转换是必需的,因为MATLAB数组只能包含值,而不能包含指针,而且指针最长可达64位(在当前硬件上)。

一个春林

我知道如何使用这个软件,但不明白它为什么好用?
您能解释一下为什么需要转换成类型吗?
*((uint64_t *)mxGetData(out)) = reinterpret_cast(new class_handle(ptr));

山口小田

您好,如果有人感兴趣,我为这个设计模式制作了一个开发工具包。https://github.com/kyamagu/mexplus

奥利弗·伍德福德

肖恩:这个数字没什么特别的。但是,不,您不需要每个类都有不同的签名,因为代码还会记录类的名称(如果愿意的话,可以是第二个签名),并在强制转换回指针时根据预期的名称进行检查。这意味着,如果您试图将一个类的指针转换为另一个类的指针,它将抛出一个错误。

中世纪商业行会

肖恩·沃克

我有一个关于class_handle.hpp的问题:

关于这条线:

#定义类句柄签名0xFF00F0A5

这个数字有什么特别之处?我可以编造任何东西,只要它在c++代码中是一致的?

我之所以问这个问题是因为我有两个独立的C++类,它们是用你的方法进行MEX ED和接口的。为了安全起见,我似乎应该为每个C++类使用一个不同的签名。这是真的吗?

中世纪商业行会

奥利弗·伍德福德

肖恩:代码和预期的一样。我这样写是为了让人们改变输入的下限以满足他们的需求。你也可以有一个上界,但这并不重要,而下界是重要的。

肖恩·沃克

这是一个伟大的提交。

然而,有一个小评论。这段代码取自你的class_interface_mex.cpp文件:

如果(!比较字符串(“火车”,cmd)) {
//检查参数
If (nlhs < 0 || NRHS < 2), coloryellow;
mexErrMsgTxt(“火车:意想不到的论点。”);
//调用该方法
虚拟实例->训练();
返回;

不应该是:

If (nlhs > 0 | NRHS > 2)

因为你的“train”方法不需要任何输入或输出?

格雷格:谢谢你的建议。是的,如果将一个实例释放到不同的mex文件中,那么锁定机制会导致问题。您当然可以解除锁定。然而,正如我在相关新闻组线程中所说的,我发现如果我不使用文件锁,当我调用“clear functions”时,MATLAB崩溃。因此,我的建议是尽可能保留锁,并设计您的软件,使每个实例都在分配它的同一个mex文件中被释放。

格雷格

非常有用的代码!

不过我发现了一些有趣的行为。

从我的观察来看,就操作系统而言,您从一个MATLAB实例中调用的所有mex-文件共享相同的内存段。也就是说,您可以在一个mex-file中创建一个c++对象,将该对象的句柄传递回MATLAB,然后在另一个mex-file中删除该对象。这似乎工作得很好,在一个类的代码创建另一个类的实例的情况下很方便。

不过,调用mexLock()和mexUnlock()会让人感到不安。mexLock和mexUnlock会自动输入当前运行的mex文件。因此,如果Class_A_mex中创建了Class_B的对象,并调用convertPtr2Mat将该指针传递回MATLAB,那么您就为Class_A_mex添加了一个额外的锁,当Class_A被删除时该锁不会被解锁。Class_B_mex delete方法似乎可以很好地删除Class_B对象,但它不知道Class_A_mex上的mexLock的任何信息。

目前,我已经在“class_handle.hpp”中创建了一个“convertPtr2MatLockless”函数,它是“convertPtr2Mat”的一个精确副本,只是它不调用mexLock()。每当创建与mex文件所用于的类不同的类的对象时,我都称其为“无锁”版本。

我对这种解决方法不太满意,但我真的不知道mexLock()有多重要。至少,不必让C++删除方法造成分段错误。

格雷格

奥利弗·伍德福德

Bin:这些成员提供了一种方法来检查您是否将一个随机内存地址强制转换为指向基类实例的指针。这样做可能会导致一些不好的事情发生,所以这是一种保护措施。

箱子

你能给我解释一下使用带有签名和名字的class_句柄的原因吗?如果我们不使用这两个成员而直接使用基类呢?

非常感谢。

保罗Dugas

如何将签名移动到模板参数中?

模板。。。

这将允许对不同的派生进行更改。

0.02美元

还Biguri

奥利弗·伍德福德

你的编译错误与这次提交无关。

费尔南多:你得到的错误似乎不言自明。您需要确保本次提交所附带的class_handle.hpp与正在编译的cpp文件位于同一个文件夹中。

Szigeti

你好
我成功地运行了这个例子,甚至在我的课上创建了新的函数,并给出了一个矩阵作为输出参数。然而,我想将我的代码导入到给定的类中,作为一个函数。它在c++中打开一个指向COM 2设备的dll。我重载了一些操作符,比如[],=,*;我读过,matlab支持重载,但这不是matla金宝appb代码。所以我有点困惑。在我看来,vs 2010编译器,我有mex设置,应该工作。但它给了我这个错误。class_interface_mex。obj: error LNK2019: unresolved external symbol "public: class std::vector > & __cdecl EEGContainer::operator[](int)" (??AEEGContainer@@QEAAAEAV?$vector@HV?$allocator@H@std@@@std@@H@Z) referenced in function "public: double * * __cdecl dummy::getEeg(void)" (?getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex.obj:错误LNK2019:未解析的外部符号“public:int_ucdecl EEGContainer::GetDataLength(void)”(?getDataLenght@EEGContainer@@QEAAHXZ)在函数“public:double**\uu cdecl dummy::getEeg(void)”中引用(?getEeg@dummy@@QEAAPEAXZ)
class_interface_mex.obj:错误LNK2019:未解析的外部符号“public:uu cdecl EEGCContainer::~EEGCContainer(void)”(??1EEGContainer@@QEAA@XZ)在函数“public:double**u cdecl dummy::getEeg(void)”中引用(?getEeg@dummy@@QEAAPEAXZ)
class_interface_mex。object: error LNK2019: unresolved external symbol "public: class EEGContainer & __cdecl EEGContainer::operator=(class EEGContainer const &)"4EEGContainer@@QEAAAEAV0@AEBV0@@Z在function "public: double * * __cdecl dummy::getEeg(void)"中引用(? getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex。obj: error LNK2019: unresolved external symbol "public: __cdecl EEGContainer::EEGContainer(int)"(??0EEGContainer@@QEAA@H@Z)在函数"public: double * * __cdecl dummy::getEeg(void)"(? getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex。obj: error LNK2019: unresolved external symbol "public: __cdecl BMRecorder::BMRecorder(void)"在函数"public: double * * __cdecl dummy::getEeg(void)"中引用0BMRecorder@@ @QEAA@XZ(? getEeg@dummy@@QEAAPEAPEANXZ)
类_接口_mex.mexw64:致命错误LNK1120:6个未解析的外部

费尔南多

大家好,我在matlab中混合class_interface_mex.cpp时遇到问题。matlab给我的错误如下:

> >墨西哥人class_interface_mex.cpp
class_interface_mex.cpp
\\aus.aero-ad.tamu.edu\UgradUsers$\f0p1107\Home\MATLAB\class_interface_mex.cpp(2): fatal error C1083: Cannot open include file: 'class_handle.hpp':没有这样的文件或目录

C:\PROGRA~1\MATLAB\R2012A\BIN\MEX.PL:错误:编译“\\aus.aero-ad.tamu.edu\UgradUsers$\f0p1107\Home\MATLAB\class\u interface\u MEX.cpp”失败。

使用mex时出错(第206行)
无法成功完成。

有没有人能帮助我,让我知道怎样才能消除这个错误?我不是编码专家,所以请尽量保持你的答案简单。任何帮助都将不胜感激。

谢谢你!

理查德·克罗泽

嗯,FEX评论框吞噬了我的库,我需要的是以下两个


typeinfo

理查德·克罗泽

为了让它在Linux上编译,我必须包括以下两个方面

因为# include <字符串>
#包括

我使用的是GCC4.4.6。它命令我使用typeinfo,我需要cstring来获取strcmp。

不过谢谢你,它对我非常有用!

Gabriele Gualandi

感谢Andreas对Unix编译的建议!!!

阿尔乔姆

就这样,奥利弗!非常感谢,精彩的贡献!

奥利弗·伍德福德

Artem:如果你想把它放在一个类目录中,那么mex文件需要放在名为private的文件夹的子目录中。

阿尔乔姆

Oliver,它就是'mex class_interface_mex。cpp',对吗?如果mex-file在非-@目录下,它可以正常工作,但在class目录下它会失败。

奥利弗·伍德福德

Artem:你是否如文件描述中所解释的那样对文件进行了mex ?

阿尔乔姆

巨大的贡献!
我想知道是否可以把类放在@class_interface目录下?在我的例子中,Matlab找不到class_interface_mex()函数。有什么建议吗?

安德烈亚斯

在非windows系统上编译代码需要一些调整。使用'raw_name()'而不是'name()'的原因是什么?前者是MS特有的。

---原版/class_handle.hpp 2012-11-08 15:34:08.000000000+0100
+++ new/class_handle.hpp 2012-11-27 16:46:50.831263148 +0100
@@ -4,12 +4,28 @@
# include < stdint.h >
# include <字符串>

+#if !(define _WIN32 || define _WIN64) //需要在linux上编译。
+ # include < string.h >
+#包括
+ #define raw_name name //最好是修改代码,使用'name()'而不是'raw_name()'
+ # endif
+


——trans /class_interface_mex.cpp 2012-11-08 16:10:26 000000000 +0100
+++ new/class_interface_mex.cpp 2012-11-27 16:46:47 375263270 +0100
@@ -1,6 +1,10 @@
# include“mex.h”
# include“class_handle.hpp”

+#if !(define _WIN32 || define _WIN64) //需要在linux上编译。
+ # include < string.h >
+ # endif
+
//我们要接口的类
类假

弗朗西斯科·Montorsi

很好!完美的C++面向对象代码与Matlab接口

马修

伟大的提交从信息性新闻组线程开发(在描述中提到)。

MATLAB版本兼容性
使用R2012b创建
与任何版本兼容
平台的兼容性
窗户 macOS Linux

社区寻宝

在MATLAB中心找到宝藏,并发现社区如何可以帮助你!

开始狩猎!