Problem in using mxSetPr with USHORT
Show older comments
I create an array in C, and the element of the array is USHORT, counting for 2 Bytes. Now, I wanna transfer this array to MATLAB workspace, using MATLAB-C API. The current method I used is to copy the value of each elements one by one in a for-loop. It is so inefficient. Therefore, I want to use pointers. However, I found the function mxSetPr demands the input type is double*. USHORT is determined by the hardware I used. Is there any similar function which can accomplish the address transformation from C to MATLAB workspace, and is valid for USHORT.
Accepted Answer
More Answers (1)
James Tursa
on 18 Feb 2022
1 vote
To attach pointers of type other than double to an mxArray, you can use the mxSetData( ) function as Jan suggests. In your case you would create an mxArray of type mxUINT16_CLASS for this.
However, this will only work if the pointer was allocated with an official API function such as mxMalloc( ) or mxCalloc( ). If the pointer points to memory allocated by standard C/C++ routines such as malloc( ) or calloc( ), or the pointer points to local variables allocated off of the stack, then the use of mxSetData( ) with these pointers will result in an assertion fault and a MATLAB crash. In these cases, you must copy the data with a loop or memcpy( ).
4 Comments
Jan
on 18 Feb 2022
When does Matlab crash after using a foreign data pointer? When the variable is used, or when it is deleted?
James Tursa
on 18 Feb 2022
Depends on the version of MATLAB. Earlier versions of MATLAB (like 10 years ago or so) did not check the pointer passed in, so the crash would happen later when the foreign pointer gets used (either on access if the foreign pointer had become invalid, or on free'ing the foreign pointer because the MATLAB Memory Manager couldn't handle the foreign pointer properly). With later versions of MATLAB the mxSetData( ) routine checks the pointer being passed in and will seg fault with an assertion failure inside the mxSetData (and friends) call itself.
There are unofficial ways to hack around this, but not advised. E.g., you could hack into the mxArray header and manually attach a foreign pointer to the pr field. Then pass that to MATLAB in a mexCallMATLAB( ) call (e.g., for plotting purposes). Then hack into the mxArray and manually NULL out that pointer. So it could be used as a means to plot raw C/C++ data without making a deep copy first. But if any little thing goes wrong and is not coded properly expect a crash.
You can also get this type of failure even with MATLAB allocated memory by improperly using the mxSetCell( ) or mxSetField( ) routines by passing in the same mxArray variable more than once. That shares the same mxArray among multiple elements (the routines attach raw pointers without making deep copies) but MATLAB doesn't know anything about it, so later on MATLAB will inadventently destroy the source mxArray even though there are shared reference copies of it still in variables. Result is a crash later on when invalid memory is accessed. This can be avoided by bumping up the reference counter, but there was never an official API function to do this. There used to be an unofficial API library function for this purpose, mxCreateReference( ), but that function was removed from the API library several years ago. Now the only way to do this is to hack into the mxArray header and manually increment the reference count field. And they keep changing the layout of the mxArray header from release to release, so these hacks are fragile to say the least.
Jan
on 18 Feb 2022
Thanks for you explanations.
Wang Yifan
on 22 Feb 2022
Categories
Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!