Convert integer to string with C ++ compatible function for Matlab Coder

I use Matlab Coder to convert some Matlab code to C ++, however I am having problems converting intergers to strings.

int2str() not supported for generating code, so I have to find another way to convert ints to strings. I tried to search for it without success. Is it possible?

+5
source share
4 answers

This can be done manually (very painful though)

 function s = thePainfulInt2Str( n ) s = ''; is_pos = n > 0; % //save sign n = abs(n); %// work with positive while n > 0 c = mod( n, 10 ); % get current character s = [uint8(c+'0'),s]; %// add the character n = ( n - c ) / 10; %// "chop" it off and continue end if ~is_pos s = ['-',s]; %// add the sign end 
+8
source

sprintf is another very simple function, so it can also work in C ++:

 x = int64(1948) str = sprintf('%i',x) 

This is also the main function used by int2str .


According to this complete list of supported features , as Matt pointed out in the comments, sprintf not supported, which is surprising. However, there is an undocumented helper function (therefore not on the list) sprintfc that seems to work and can be used equivalently:

 str = sprintfc('%i',x) 
+6
source

You can also invoke C runtime sprintf or snprintf using coder.ceval . It also makes it easy to support floating point helper functions. You can also change the formatting as desired by changing the format string.

Suppose your compiler provides snprintf , which you can use:

 function s = cint2str(x) %#codegen if coder.target('MATLAB') s = int2str(x); else coder.cinclude('<stdio.h>'); assert(isfloat(x) || isinteger(x), 'x must be a float or an integer'); assert(x == floor(x) && isfinite(x), 'x must be a finite integer value'); if isinteger(x) switch class(x) % Set up for Win64, change to match your target case {'int8','int16','int32'} fmt = '%d'; case 'int64' fmt = '%lld'; case {'uint8','uint16','uint32'} fmt = '%u'; otherwise fmt = '%llu'; end else fmt = '%.0f'; end % NULL-terminate for C cfmt = [fmt, 0]; % Set up external C types nt = coder.opaque('int','0'); szt = coder.opaque('size_t','0'); NULL = coder.opaque('char*','NULL'); % Query length nt = coder.ceval('snprintf',NULL,szt,coder.rref(cfmt),x); n = cast(nt,'int32'); ns = n+1; % +1 for trailing null % Allocate and format s = coder.nullcopy(blanks(ns)); nt = coder.ceval('snprintf',coder.ref(s),cast(ns,'like',szt),coder.rref(cfmt),x); assert(cast(nt,'int32') == n, 'Failed to format string'); end 

Note that you may need to tweak the format string to match the hardware you are running on, as this assumes that long long is available and matches 64-bit integers with it.

+1
source

I use the following workaround to enable sprintf for general use with Matlab Coder:

1) Create the following m file named "sprintf.m", preferably in the NOT folder on your Matlab path:

 function s = sprintf(f, varargin) if (coder.target('MATLAB')) s = builtin('sprintf',f,varargin{:}); elseif (coder.target('MEX')) s = builtin('sprintf',f,varargin{:}); else coder.cinclude('stdio.h'); s = char(zeros(1024,1)); cf = [f,0]; % NULL-terminated string for use in C coder.ceval('sprintf_s', coder.ref(s(1)), int32(1024), coder.rref(cf(1)), varargin{:}); end 

2) Make sure sprintf not specified as extrinsic via coder.extrinsic

3) Specify the folder containing the newly created "sprintf.m" as an additional include directory when generating code. If you use the codegen function, this can be done using the -I . If you use the Coder application, this can be done in the "Advanced Settings → User Code → Additional Directories" section of the "Create" tab.

4) Convert from int to string as follows: s=sprintf('%d',int32(n));

Notes:

  • The specified "sprintf.m" obscures the sprintf built-in function and executes it instead of the built-in function every time you call sprintf from the generated code. By placing this file in a folder that is not in the Matlab path, you do not call it from any other code created to run in Matlab. The call to coder.target also helps return to the built-in function if this call is called in a regular Matlab session or from a MEX file.
  • The code above limits the result to 1023 characters (a trailing zero is required at the end). The sprintf_s call tells the C ++ compiler to throw an exception at runtime if the result exceeds this value. This prevents memory corruption, which is often captured much later, and is harder to track callbacks. This limit can be changed according to your own requirements.
  • Numeric types must be converted to the correct class before passing them to sprintf , for example. add int32 to match the %d character in the format string. This requirement is the same when using fprintf with Matlab Coder. However, in the case of fprintf Matlab Coder catches type errors for you. For sprintf , the C ++ compiler may fail or the resulting string may contain errors.
  • String arguments must be NULL-terminated manually for use in C calls, as Matlab Coder does not do this automatically (credit for Ryan Livingston to indicate this). The above code ensures that the format string f is NULL terminated, but the NULL termination of the other string arguments remains the responsibility of the calling function.
  • This code has been tested on a Windows platform with Visual Studio C ++ compiler and Matlab R2016a (Matlab Coder 3.1), but it is expected to work in most other environments.
+1
source

All Articles