I have a C++ class. How can I interface to it through a MATLAB class?
37 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Oliver Woodford
le 3 Fév 2011
Réponse apportée : Sven Nießner
le 8 Oct 2020
I have a C++ class. Sometimes I write my own, but I found this one online. It's great, and I'd like to use it in MATLAB.
The class has a train() function, which takes in data and creates some structure which it then stores in memory. It also has a test() function, which then uses the structure computed with train(). The idea is that you train once, then test on lots of different data. Because I have lots of different training data, I will want to have several instances of this class at the same time, so the approach needs to cope with that.
How can I create an interface to this C++ class in MATLAB?
0 commentaires
Réponse acceptée
David Foti
le 18 Fév 2011
There is no direct way to interface to the C++ class from MATLAB. You can use a MEX file to construct a new instance of the C++ object and return a pointer to it in MATLAB by encoding the pointer in an int64 matrix for example. Then you can pass this matrix back to the same or a different MEX file that will decode it and use it. You could use a MATLAB class to encapsulate the MEX files that use the C++ class and the encoding of the C++ pointer. A handle class destructor could be used to call a MEX file that deletes the C++ object.
2 commentaires
Plus de réponses (5)
Andrew Newell
le 3 Fév 2011
In the Matlab help browser, see Matlab > User Guide > External Interfaces > Calling C/C++ and Fortran Programs from MATLAB Command Line
Thomas Lai
le 9 Août 2012
As far as I know, mex does not support object persistence past its basic predefined numeric classes. I tried returning the pointer to matlab and recast it in another mex function call but this just does not work, even when I declared the object as global static.
2 commentaires
Malcolm Cowan
le 17 Nov 2012
I have interfaced Matlab objects with C++ objects. One way that works is this: you hold all the C++ objects in a list and make this list a member of the DLL. I use a CArray object and it hold a list of smart pointers to the objects. The list is set up in the DLL InitInstance method and cleared in the DLL ExitInstance method. Each object in the list has a numerical 'handle' value. When an object is created - in response to a request from Matlab via the MEX interface, it is added to the list and its handle value is set. This handle value is returned to Matlab and is held as a property of the Matlab object. All subsequent interactions between the Matlab object and its C++ partner object use this handle value to select the C++ object from the list so that the right method can be invoked. This has worked for me for a number of years. It may sound complicated but it is just a matter of having an object in Matlab and a partner C++ object in the MEX file and managing data exchange between them. Persistency of the C++ objects is managed by holding them in the list as a member of the DLL app. Advise if you want more explanation or an example.
2 commentaires
Yvo
le 26 Juin 2014
Hello!
I think I have the same problem, but I can't solve it, cause I am an absolute beginner in programming, not an expert. Here is my problem:
I writing my bachelor thesis at cologne university of applied sciences about color shading of sensors. Therefore I use a RODEON VR Head. I put a camera on it and with it I can adjust different angles. I want to simulate angles of entry.
I wrote a program in Matlab (Mathworks). I want to control the camera and the RODEON Head from Matlab. To control the RODEON Head I got the whole API, C-Code, dll, lib from RODEON. To use c-Code in Matlab I need a mex-function. I wrote a mex-function and wrote the c++-code to control the RODEON Head. It is a cpp-file and the compiler is the Microsoft Visual 2008. Sometimes it works, but often not. There are some bugs, but I am not a programmer to solve the problems. I can initialize the RODEON Head from Matlab. Sometimes. Sometimes the head does not initialize. I don't know why. When I get it, I can move the head.
The CODE:
I initialize the RODEON head:
RCIH hRCI = RODEONcontrol_init(argc, arg)
About that command I get the connection and the head is ready. I always need the Data typ RCIH hRCI for all commands!
To control the angles I use the function:
RODEONcontrol_goto(hRCI, hAngle, vAngle) As you see, I need the data type hRCI, too.
Now my question. When I start the program, the head shall be initialize. Then I command the angles, the head moves to the position and stays so long there, till I command a new angle. Therefore, The program needs every times the data type hRCI.
At the moment I have one mex-function for the initialization and the "goto"-function.That means, that the head will be initialized every times again, when I command a new angle. That shouldn't be!
Ideally it should be three Mex-functions:
1. one to initialize (init) 2. one to command the angles (goto) 3. one to deinitialize the RODEON head and to get into the park position (deInit)
And this is the problem, where I don't get it. i am not an expert in programing and I don't know C++. To realize it, I think I get the data typ hRCI from the first function (init) and deliver it every times to the "goto"-function.
=> I call the "init"-function, I get a return value (data typ hRCI), I deliver the data type every times together with the angles from Matlab to the "goto"-function.
How does it work? Does it work? Or how can I solve this problem? It is allowed to get such a specific data type from c++ to Matlab and give it back to c++? Do you understand my problem?
It would be so great, if you could help me. I can't go on with my work:( Maybe you can help me? Best wishes and thousands of thanks!!!
Yvo
THE CODE:
#include "mex.h"
#ifndef __stdcall #define __stdcall _stdcall #endif
#include "windows.h" #include "TCHAR.h"
#define RODEON_CONTROL_IMPORT_DYNAMIC #include "RodeonControl.h" RODEON_CONTROL_IMPORT
void mexFunction(int nlhs, mxArray plhs[], int nrhs, const mxArray *prhs[]) { (void) plhs; / unused parameters */
int argc = NULL; // Parameters are optional. I can set it "NULL". The producer of RODEON told me
_TCHAR ** argv = NULL;
_TCHAR **envp = NULL;
/*
* read Input Data
*/
const mxArray *hAngle;
const mxArray *vAngle;
double h;
double v;
hAngle = prhs[0]; // horizontal angle, INPUT
vAngle = prhs[1]; // vertical angle, INPUT
h = (double)(mxGetScalar(hAngle));
v = (double)(mxGetScalar(vAngle));
// === optional === //
//the following few lines are optional, and intend to show, how to expand or define the command line for initalisation
_TCHAR * arg[] = { _T("-v"), //turn on verbosity
_T("-swm") //we are not threaded an therefor need no messages
};
//int argc = sizeof(arg)/sizeof(_TCHAR *);
//fully automated initialisation
// reads in all configuration parameters given by the command line in argc & argv and the configuration files as well as
// the assembly file and gets connected to the Rodeon device.
// Returns a valid Rodeon Control Instance Handler on success, otherwise 0.
/*
*argc: count of entries in argv-array
*TCHAR ** argv: pointerarray to strings, which are passed as parameters
*/
RCIH hRCI = RODEONcontrol_init(argc, arg);
//check, whether we got a valid handle
if(!hRCI)
{
_tprintf(_T("Program terminated\n"));
return;
}
//wait, until the device becomes ready
// executes an op_wait-command as described in the RODEONscript language reference.
// return 0 if successful, otherwise -1,
// RODEONcontrol_op_wait(hRCI, -1);
{
// == movement == !!!
// Goes to the coordinates (horizontal/vertical) given by the parameters, and waits until reached.
// Return 0 if successful, otherwise -1.
// The angles, which will be reached depends on additional restrictions made by the configuration
if(RODEONcontrol_goto(hRCI, h, v)) // handler to RODEON Control, hori angle in degrees, veri angle in degrees
{
_tprintf(_T("Program terminated Stelle 2\n"));
return;
}
}
//and shut down the device
// Disconnects from the device, and frees up the instance identified by hRodeon.
// Returns 0, if no error occured. Otherwise -1.
RODEONcontrol_deinit(hRCI);
return;
}
Jon C
le 11 Sep 2015
I suggest to look at the example MEX file and class wrapper in this GitHub repo. This is a solution I came up with a little while ago, and I just now saw this question. Hopefully this will be helpful to someone.
Implementation Overview
For your C++ class, class_type, mexFunction uses static data storage to hold a persistent (between calls to mexFunction) table of integer handles and smart pointers to dynamically allocated class instances. A std::map is used for this purpose, which facilitates locating known handles, for which only valid instances of your class are guaranteed to exist:
typedef unsigned int handle_type;
std::map<handle_type, std::shared_ptr<class_type>>
A std::shared_ptr takes care of deallocation when either (1) a table element is erased via the "delete" action or (2) the MEX-file is unloaded.
To prevent the MEX-file from unloading while a MATLAB class instances exist, mexLock is called each time a new C++ class instance is created, adding to the MEX-file's lock count. Each time a C++ instance is deleted mexUnlock is called, removing one lock from the lock count.
Design goals
- Manage multiple persistent instances of a C++ class
- Small consecutive integer handles used in MATLAB (not cast pointers)
- Transparently handle resource management (i.e. MATLAB never responsible for memory allocated for C++ classes): (a) No memory leaked if MATLAB fails to issue "delete" action. (b) Automatic deallocation if MEX-file prematurely unloaded.
- Guard against premature module unloading
- Validity of handles implicitly verified without checking a magic number
- No wrapper class or functions mimicking mexFunction, just an intuitive switch-case block in mexFunction.
Note that these goals should be acheved without regard to any MATLAB class, but which can also help address memory management issues. As such, the resulting MEX-file can safely be used directly (but not too elegantly).
Use
- Enumerate the different actions (e.g. New, Delete, Insert, etc.) in the Actions enum. For each enumerated action, specify a string (e.g. "new", "delete", "insert", etc.) to be passed as the first argument to the MEX function in MATLAB.
- Customize the handling for each action in the switch statement in the body of mexFunction (e.g. call the relevant C++ class method).
Sven Nießner
le 8 Oct 2020
NET.addAssembly('System.Core');
TCHAR = NET.createArray('System.Char',4096);
Or im wrong?
0 commentaires
Voir également
Catégories
En savoir plus sur Write C Functions Callable from MATLAB (MEX Files) dans Help Center et File Exchange
Produits
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!