Petur Olsen Petur Olsen - 3 months ago 21
C Question

Converting a C char array into a Matlab String using Matlab Coder

I have some code written in Matlab that I am converting into C code using Matlab Coder.

I have written a C function that I want to call from the generated C code. This works, so far so good.

The problem is that one of the parameters to the C function is a char** used to output a string.

I accomplish this by making an opaque char* and using coder.wref to get the char**. But how do I convert the opaque char* to a Matlab string so I can return it from my function?

The code goes something like this:

function [status,out] = cfun()
buf = coder.opaque('char *', 'NULL');
len = coder.opaque('size_t ', 'NULL');
status = 0;
status = coder.ceval('_cfun', coder.wref(buf), coder.wref(len));

out = buf; % How do I convert buf into a Matlab string here??
end


_cfun will write some data to buf and write the length into len.

My current solution, which almost works, is to manually make a char array in Matlab and transfer to data. Like this:

length = cast(len, 'int32');
out = char(zeros(1,length+1));
for i = 1:(length+1)
out(i) = cast(buf(i), 'int32');
end


The C code generated from this makes no sense and loops infinitely, but I can manually update it to work. However this requires a manual update every time I rerun the code generation.

The C code looks like this:

i18 = length + 1L;
copyfrom = (int)i18;
i = 1;
while (i <= copyfrom) {
source_str->data[0] = (signed char)(int)buf;
i = 2;
}


I can update it to work:

i18 = length + 1L;
copyfrom = (int)i18;
i = 1;
while (i <= copyfrom) {
source_str->data[i-1] = (signed char)(int)(buf[i-1]);
i = i+1;
}


So, is there a way to convert the char* + length into a Matlab string? Or is there a better way of doing what I am trying to?

Answer

It's a bit wasteful, but you could allocate a MATLAB char array and memcpy the data into it:

mllen = cast(len,'int32'); % or int64
mlbuf = blanks(mllen); % allocate character vector
coder.ceval('memcpy',coder.wref(mlbuf),buf,len);
use(mlbuf);

You may want a +1 or -1 on sizes based upon whether or not len counts a NULL terminator and if you want it.

If you can somehow figure out len before the call to _cfun then you can just pass mlbuf to _cfun and forget the copy.

The generated code is indexing with 0 and producing an infinite loop because as far as Coder is concerned, buf is a 1-by-1 coder.opaque. You would get an index out of bounds error if you generated a MEX file and ran it.