I'm trying to call a dll function in matlab. I have a C++ struct as shown in sixense.h:
typedef struct _sixenseControllerData {
float pos[3];
float rot_mat[3][3];
float joystick_x;
float joystick_y;
float trigger;
...
} sixenseControllerData;
and functions I could call:
SIXENSE_EXPORT int sixenseInit( void );
SIXENSE_EXPORT int sixenseGetAllNewestData( sixenseAllControllerData * );
I can easily get this to work with calllib('sixense','sixenseInit')
since there is no input, but for the function sixenseGetAllNewestData I need to have a struct pointer. I realize that libstruct is what I need to use. However, I don't seem to be doing it right.
So I tried libstruct like so:
libstruct('sixenseControllerData')
and I get the error:
??? Error using ==> feval
Undefined function or variable 'lib.sixenseControllerData'.
Error in ==> libstruct at 15
ptr=feval(['lib.' structtype]);
EDIT: here is my current unedited proto file: http://pastebin.com/PemmmMqF
the full header file is available here: https://github.com/rll/sixense/blob/master/include/sixense.h
For C structures,
loadlibrary
generates types named:s_{NAME}
where{NAME}
is the name of the structure. In your case we create a pointer as:We can see this fact by instructing MATLAB to generate a prototype file:
A prototype file is a file of MATLAB commands which we can modify and use in place of a header file. In this case, the file will contain something like:
sixense_proto.m
Unfortunately, a limitation of
loadlibrary
is that it does not support nested structure very well, especially if a structure contains a pointer to another structure (or an array in this case):So you will not be able to directly create the
sixenseAllControllerData
structure on the MATLAB side, which is defined in the C header file as:According to the following discussion, one workaround is to "unroll"/"flatten" the array into separate variables. You can either do this in a copy of the header file, or making the changes in the generated prototype file (which I think is the preferred way). You can do this without having to recompile the shared library.
In your case, change the nested structure in the generated
sixense_proto.m
file into:Now we can create a pointer to this structure, and call the C method:
A completely different solution is to write a MEX-function to interface with the library. It is just like any other C/C++ code, only using
mxArray
and the MX-API to interface with MATLAB...Example:
To test the above, I created a simple DLL with similar structures, and implemented the above solution. Here is the code if someone wants to test it:
helper.h
mylib.h
mylib.c
After compiling the above into a DLL, we generate the initial prototype file:
I edit the prototype file as described before:
Now we can finally invoke functions exposed by the DLL: