how to read strings with multiple null (\0) terminators when using calllib functions

25 views (last 30 days)
Hi everyone,
I've got a problem reading data from a device using external C dlls and calllib function.
The alias .m header file is something as below:
int ws_read_configdata ( const char * name , char * buffer , int buffersize , int * nread );
% fcns.name{fcnNum}='ws_read_configdata'; fcns.calltype{fcnNum}='cdecl'; fcns.LHS{fcnNum}='int32'; fcns.RHS{fcnNum}={'cstring', 'cstring', 'int32', 'int32Ptr'};fcnNum=fcnNum+1;
or in the real .h file, as:
% *@param name [in] Previously created WaveShaper name
% *@param buffer [out] buffer to hold configuration data
% *@param buffersize [in] buffer size
% *@param nread [out] configuration data read in bytes
% *@return status code
% */
% int ws_read_configdata(const char* name, char* buffer, int buffersize, int* nread);
The matlab code I used to retrieve the data from the device is like:
bufsize = 10000000;
bufread = 0;
buf = blanks(bufsize);
[rc, a, b, c] = calllib(libname, 'ws_read_configdata', wsname, bufptr, bufsize, 0);
which returns me in variable b, only the first eight CHARS ['37CB39A6']. The remaining of the data is unreachable. The other returned values are shown below
rc = 0; % error check code, 0 = success
a = 58113; % serial number of device
b = '37CB39A6'; % returned data, WRONG! ONLY FIRST EIGHT CHARS
d = 6061152; % bytes that have been read
when I tried to use libpointers like:
bufsize = 10000000;
bufread = libpointer('int32Ptr', bufsize);
buf = blanks(bufsize);
bufptr = libpointer('string', buf);
[rc, a, bufptr.value, c] = calllib(libname, 'ws_read_configdata', wsname, bufptr, bufsize, bufread);
the problem remains the same.
rc = 0;
a = 58113;
bufptr.value = '37CB39A6';
c = 6061152;
yet now
bufread.value = 6061152
The content retrieved data by other methods (using executable file) is like
that is to say, the there are \0 characters in the data.
Any ideas how can I deal with this issue?
Thanks
Deming

Accepted Answer

Philip Borghesani
Philip Borghesani on 23 Mar 2017
Modify the prototype m file to declare the buffer variable as int8Ptr (or uint8Ptr) instead of cstring. Then pass an int8 buffer:
bufptr = libpointer('int8Ptr', zeros(bufsize,1,'int8'));
[rc, ~, ~ , c] = calllib(libname, 'ws_read_configdata', wsname, bufptr, bufsize, 0);
bufptr.value
If you want the results in a character array you can convert with the char function. bufferwithnulls=char(bufptr.value)
  2 Comments
Deming Kong
Deming Kong on 23 Mar 2017
Hi Philip,
Thank you very much for your prompt answer. It just worked like magic! :) I really appreciate it.
BR, Deming
Thomas Carpenter
Thomas Carpenter on 15 Dec 2022
Is there any way to force MATLAB to force MATLAB to detect int8 rather than as cstring? It seems like a horrible hack having th change the API entry definitions in my DLL file to the wrong data type (affects other software that uses the DLL) just because MATLAB does bizarre things.
We used to use LPSTR from Windows.h which MATLAB would sometimes pick up as int8Ptr rather than cString (even though LPSTR is literally a typedef for char*) - not always though! However that works only intermittently to force the issue and is no good if you also need to support Linux compiles (unless we start having compatibility headers with random type defines which is just ugly).
When it was picking things up as int8Ptr our code worked fine, but having recently changed the API to char* to support Linux nicely, it's suddenly broken everything in obscure ways. For example if you have an API that's say:
void populateBuf(char* buf, int bufLen)
Which will fill up to bufLen characters into the buffer buf.
Then call it from MATLAB with:
bufIn = char(zeros(1,10,'int8')); % Just an example, can be any array with nulls in it.
result = calllib('populateBuf', bufIn, 10);
When it was int8Ptr it would work absolutely fine. However when it detects as cString MATLAB will hard fault from heap corruption even through the DLL wrote <10 characters into a buffer which is supposed to be 10 characters long. MATLAB appears to have truncated the buffer at the first null character and passed in a non-null pointer to a zero-length buffer (on return MATLAB tries to free this buffer and corrupts its memory space).

Sign in to comment.

More Answers (0)

Categories

Find more on C Shared Library Integration in Help Center and File Exchange

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!