Code covered by the BSD License  

Highlights from
Example MATLAB class wrapper for a C++ class

4.91667

4.9 | 14 ratings Rate this file 109 Downloads (last 30 days) File Size: 3 KB File ID: #38964

Example MATLAB class wrapper for a C++ class

by

 

09 Nov 2012 (Updated )

An example of how to safely encapsulate a C++ class in a MATLAB class, via a mex interface.

| Watch this File

File Information
Description

This package provides an example of how to wrap a C++ class in a MATLAB class, via a mex interface, safely, without memory leaks, whilst achieving an interface in MATLAB that is similar to the underlying C++ interface.

After downloading, first mex the C++ wrapper using:
>> mex class_interface_mex.cpp

Then test the various methods:
>> a = class_interface(); % Create a class instance
>> train(a) % Train the class - dummy method
>> test(a) % Test the class - dummy method
>> clear a; % Destroy the instance

Look in class_interface.m and class_interface_mex.cpp to see how this is implemented, and copy the structure to interface with your own C++ classes.

This submission is inspired by the following newsgroup thread:
http://www.mathworks.com/matlabcentral/newsreader/view_thread/278243
Thanks to all those who have contributed.

Acknowledgements

This file inspired Matlab Class Wrapper For A C++ Implementation Of A Quadtree, Ray Casting For Deformable Triangular 3 D Meshes, Message Passing Algorithm For Decoding Binary Ldpc Codes, Felicity, and Crobarcro/Mcode Cpp Utilities.

MATLAB release MATLAB 8.0 (R2012b)
Other requirements C++ compiler
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (34)
26 Aug 2014 David

Looks intriguing, but I get the following error message when I try to compile: fatal error C1083: Cannot open include file: 'stdint.h': No such file or directory.

I read up online a bit and it's because my version of Visual Studio (2008) does not support this library. If Matlab uses visual studio to compile, you'll need to download these libraries to run and add an -i argument to tell the file location when compiling: https://code.google.com/p/msinttypes/downloads/detail?name=msinttypes-r26.zip

08 Apr 2014 Hanse  
04 Apr 2014 Oliver Woodford

Joel: It would seem to be valid, but I cannot comment on whether it is safe. I would also imagine the pointer points to a static string, though. Try it.

04 Apr 2014 Joel Andersson

Is it safe to change the type of class_handle<base>::name_m to const char*? I imagine that "typeid(base).name()" returns a pointer to something with static storage.

18 Mar 2014 Oliver Woodford

An Tran Lam: The type cast is required because MATLAB arrays can only contain values, not pointers, and pointers can be up to 64 bits long (on current hardware).

13 Mar 2014 An Tran Lam

I know how to use the software, but don't understand why it works?
Can you explain why do you need to cast into <uint64_t> type?
*((uint64_t *)mxGetData(out)) = reinterpret_cast<uint64_t>(new class_handle<base>(ptr));

13 Mar 2014 Kota Yamaguchi

Hello, I made a development kit for this design pattern, if anyone interested. https://github.com/kyamagu/mexplus

10 Jan 2014 Oliver Woodford

Shawn: There's nothing special about that number. But, no, you don't need a different signature per class, as the code also records the name of the class (a second signature, if you like), and checks this against the expected name when casting back to a pointer. This means it would throw an error if you tried to cast a pointer of one class to a pointer of another.

10 Jan 2014 Hanse  
08 Jan 2014 Shawn Walker

I have a question about class_handle.hpp:

Regarding this line:

#define CLASS_HANDLE_SIGNATURE 0xFF00F0A5

What is so special about that number? Could I make up anything, as long as it is consistent in the C++ code?

The reason I ask is if I have two separate C++ classes that are mex-ed and interfaced using your approach. It seems I should use a different signature for each C++ class, for safety's sake. Is this true?

07 Jan 2014 Hanse  
06 Jan 2014 Oliver Woodford

Shawn: The code is as intended. I wrote it that way with the intention that people would change the lower bound on number of inputs to suit their needs. You could have an upper bound too, but it's not vital, whereas a lower bound is.

06 Jan 2014 Shawn Walker

This is a great submission.

However, one minor comment. This code is taken from your class_interface_mex.cpp file:

if (!strcmp("train", cmd)) {
// Check parameters
if (nlhs < 0 || nrhs < 2)
mexErrMsgTxt("Train: Unexpected arguments.");
// Call the method
dummy_instance->train();
return;

Shouldn't it be:

if (nlhs > 0 || nrhs > 2)

because your "train" method does not need any inputs or outputs?

04 Jan 2014 Oliver Woodford

Greg: Thanks for your input. Yes, the locking mechanism causes problems if you free an instance in a different mex file from that in which it was allocated. You can certainly remove the locking. However, as I stated in the associated newsgroup thread, I found that MATLAB crashes when I call "clear functions" if I don't use the file lock. As such, my advice is to keep the lock where possible, and design your software such that each instance is freed in the same mex file it is allocated in.

03 Jan 2014 Greg

Very useful code!

Found some interesting behavior though.

From my observations, as far as the operating system is concerned, all mex-files that you call from a single instance of MATLAB share the same memory segmentation. That is, you can create a C++ object in one mex-file, pass the handle to that object back into MATLAB, then delete the object in a different mex-file. This seems to work just fine and is handy in the case where the code of one class creates instances of another class.

This gets funky with the calls to mexLock() and mexUnlock() though. mexLock and mexUnlock are automatically keyed to the currently-running mex-file. So, if an object of Class_B is created inside Class_A_mex and convertPtr2Mat is called to pass that pointer back to MATLAB, you've just added an extra lock to Class_A_mex that won't be unlocked when Class_A is deleted. The Class_B_mex delete method seems to delete the Class_B object just fine, but it doesn't know anything about the mexLock on Class_A_mex.

For the moment, I've created a workaround by creating a "convertPtr2MatLockless" function in "class_handle.hpp" that's an exact copy of "convertPtr2Mat" except that it doesn't call mexLock(). I call the "Lockless" version whenever creating an object of a different class than the one the mex file is for.

I'm not all that happy with that workaround, but I don't really know how important the mexLock() is. At the very least, it doesn't appear to be necessary to keep the C++ delete methods from causing segfaults.

02 Jan 2014 Greg  
27 Sep 2013 Oliver Woodford

Bin: Those members provide a means of checking that you are not casting a random memory address to a pointer to an instance of the base class. Doing that could lead to some bad things happening, so it is a protection against that.

09 Aug 2013 Bin

Can you explain to me what the reason for using class_handle with signature_m and name_m? What if we don't use those two members and just use the base class directly?

thank you very much.

21 May 2013 Paul Dugas

How about moving the SIGNATURE into the template parameters?

template<class base, uint32_t SIGNATURE> ...

This would allow it to be changed for different derivations.

$0.02

16 May 2013 Ander Biguri  
10 Mar 2013 Oliver Woodford

Szigeti: your compile error is not related to this submission.

Fernando: the error you get seems self explanatory. You need to make sure class_handle.hpp, which comes with this submission, is in the same folder as the cpp file being compiled.

10 Mar 2013 Szigeti

Hello
I have run the example successfully, and even managed to make new functions, in my class, and gave a matrix as an out parameter. However I want to import my code into the given class, as a function. It opens a dll in C++ to a COM 2 device. I have overloaded some operator like [], =, *; I have read that matlab support overloading, but this is not matlab code. So I am confused a bit. In my opinion the vs 2010 compiler that I have mex -setup-ed, should work. But it gives me this error. class_interface_mex.obj : error LNK2019: unresolved external symbol "public: class std::vector<int,class std::allocator<int> > & __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 : error LNK2019: unresolved external symbol "public: int __cdecl EEGContainer::getDataLenght(void)" (?getDataLenght@EEGContainer@@QEAAHXZ) referenced in function "public: double * * __cdecl dummy::getEeg(void)" (?getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex.obj : error LNK2019: unresolved external symbol "public: __cdecl EEGContainer::~EEGContainer(void)" (??1EEGContainer@@QEAA@XZ) referenced in function "public: double * * __cdecl dummy::getEeg(void)" (?getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex.obj : error LNK2019: unresolved external symbol "public: class EEGContainer & __cdecl EEGContainer::operator=(class EEGContainer const &)" (??4EEGContainer@@QEAAAEAV0@AEBV0@@Z) referenced in 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) referenced in function "public: double * * __cdecl dummy::getEeg(void)" (?getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex.obj : error LNK2019: unresolved external symbol "public: __cdecl BMRecorder::BMRecorder(void)" (??0BMRecorder@@QEAA@XZ) referenced in function "public: double * * __cdecl dummy::getEeg(void)" (?getEeg@dummy@@QEAAPEAPEANXZ)
class_interface_mex.mexw64 : fatal error LNK1120: 6 unresolved externals

31 Jan 2013 Fernando

hello everyone, I am having trouble when mexing the class_interface_mex.cpp in matlab. The error that matlab gives me is the follwing:

>> mex 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': No such file or directory

C:\PROGRA~1\MATLAB\R2012A\BIN\MEX.PL: Error: Compile of '\\aus.aero-ad.tamu.edu\UgradUsers$\f0p1107\Home\MATLAB\class_interface_mex.cpp' failed.

Error using mex (line 206)
Unable to complete successfully.

Could anyone help me by letting me know how I can get rid of this error? I am no expert at coding so please try to keep your answer as simple as possible. Any help will be much appreciated.

Thank you!

12 Jan 2013 Richard Crozier

Hmmm, the FEX comment box gobbled my libraries, it's the following two that I needed

cstring
typeinfo

12 Jan 2013 Richard Crozier

I had to include both of the following to get it to compile on Linux

#include <cstring>
#include <typeinfo>

I'm using gcc 4.4.6. It ordered me to use typeinfo, I needed cstring to get strcmp.

Thanks for this though, it's incredibly useful to me!

02 Jan 2013 Gabriele Gualandi

Thank you Andreas for you suggestion about compiling in Unix!!!

18 Dec 2012 Artem

That's it, Oliver! Thanks a lot, a wonderful contribution!

18 Dec 2012 Oliver Woodford

Artem: If you want to put this in a class directory then the mex file needs to go in a subdirectory of that folder called private.

18 Dec 2012 Artem

Oliver, It is just 'mex class_interface_mex.cpp', right? It works fine if the mex-file is in a non-@ directory, but in the class dir it fails.

17 Dec 2012 Oliver Woodford

Artem: Did you mex the file, as explained in the file description?

17 Dec 2012 Artem

Great contribution!
I wonder if it is possible to put the class in @class_interface directory? In my case, Matlab cannot find class_interface_mex() function. Any suggestions?

27 Nov 2012 Andreas

code needs some tweaking to compile on non-windows systems. What's the reason for using 'raw_name()' instead of 'name()'. The former is MS specific.

--- orig/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 <string>

+#if !(defined _WIN32 || defined _WIN64) // needed to compile on linux.
+ #include <string.h>
+ #include <typeinfo>
+ #define raw_name name // it would be better to change the code so that we use 'name()' instead of 'raw_name()'
+#endif
+


--- orig/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 !(defined _WIN32 || defined _WIN64) // needed to compile on linux.
+ #include <string.h>
+#endif
+
// The class that we are interfacing to
class dummy
{

09 Nov 2012 Francesco Montorsi

Works great! perfect to start interfacing C++ object-oriented code to MATLAB

09 Nov 2012 Matthew

Great submission developed from an informative newsgroup thread (referred to in description).

Updates
12 Dec 2012

Fix compile error in Linux - thanks to Andreas for highlighting the issue.

02 Jan 2013

2nd attempt to fix compilation under linux.

14 Jan 2013

Add #includes suggested by Richard Crozier (thanks) to fix compilation in Linux.

Contact us