0

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?

2
  • Curious, Why L in length + 1L; and all the casts in the C code? Better to post definitions of i18, length, copyfrom, i, source_str, buf to see whats is going on. As the post stands now, I find it unclear. Commented Aug 17, 2016 at 16:03
  • This is generated code from Matlab. So the L and the casts are Matlab's decision. I think the L is to avoid and check for integer overflow (I removed some checks in the code). The definitions aren't really important unless you want to start debugging why the for loop is not generated correctly. But the answer below works, so I will not spend more time on it. Commented Aug 18, 2016 at 7:49

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This worked, thanks! I can not figure out len before the call to _cfun, but it works like this, so that's perfect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.