S-Function String Parameter C++

20 vues (au cours des 30 derniers jours)
Nils Gerke
Nils Gerke le 13 Août 2018
Commenté : Titus Edelhofer le 31 Août 2018
Hey,
I've trouble reading the value of a string passed to MATLAB as an S-Function parameter in C++:
std::string str(mxArrayToString(ssGetSFcnParam(S,0)));
Throws the following exception:
Program: C:\windows\SYSTEM32\MSVCP140D.dll
File: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xstring
Line: 1181
Expression: invalid null pointer
For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)
MATLAB.exe has triggered a breakpoint.
Exception thrown at 0x00007FFB6C9A0A63 (test.mexw64) in MATLAB.exe: 0xC0000005: Access violation reading location 0x0000000000000000.
> throw_segv_longjmp_seh_filter()
throw_segv_longjmp_seh_filter(): invoking THROW_SEGV_LONGJMP SEH filter
> throwSegvLongjmpFilter()
MATLAB.exe has triggered a breakpoint.
The program '[19672] MATLAB.exe' has exited with code 0 (0x0).
For debugging purposes I splitted it up:
const mxArray* pArrayValue = ssGetSFcnParam(S,0);
const char* pCharArray = mxArrayToString(pArrayValue);
std::string str(pCharArray);
pCharArray points to:
0x000000000000000
I am using VS 14.0.25431.01 Update 3 on Win 10 Pro 17134.165 with Matlab 2018a. I found code in our companies repository where both of the above code snippets are working, in MATLAB 2013b, what am I doing wrong? Is this syntax invalid in 2018a?
Edit 31.08.18:
I added an example:
#define S_FUNCTION_LEVEL 2
#define S_FUNCTION_NAME sfun_pass_string
#include "simstruc.h"
#include <string>
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 1);
ssSetSFcnParamTunable(S, 0, SS_PRM_NOT_TUNABLE);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
if (!ssSetNumInputPorts(S,1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S, 1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetNumSampleTimes(S, 1);
ssSetOptions(S, SS_OPTION_CALL_TERMINATE_ON_EXIT);
}
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, INHERITED_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
ssSetModelReferenceSampleTimeDefaultInheritance(S);
}
#define MDL_START
static void mdlStart(SimStruct *S)
{
mexPrintf("class of parameter: %s", mxGetClassName(ssGetSFcnParam(S,0)));
const mxArray* pArrayValue = ssGetSFcnParam(S,0);
const char* pCharArray = mxArrayToString(pArrayValue);
std::string string_1(pCharArray);
mexPrintf(string_1.c_str());
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
}
static void mdlTerminate(SimStruct *S)
{
}
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif
  3 commentaires
Nils Gerke
Nils Gerke le 30 Août 2018
You might be right.
mxArray test = *pArrayValue;
Gives me a compiler error:
Error C2079 'test' uses undefined struct 'mxArray_tag'
I've only one Parameter that I pass to the S-Function, in the model I write the string in double quotes.
I'm a C++ beginner, but still I really don't get whats wrong with that code. If I pass a string to the simulink model I would suspect (based on the documentation) that
ssGetSFcnParam(S,0)
gives me back my string as mxArray and that
mxArrayToString()
would convert it to a std::string. Or is this assumption wrong?
Titus Edelhofer
Titus Edelhofer le 30 Août 2018
Nils,
mxArray test = ...
will not work, since you always have to use pointers ...
Titus

Connectez-vous pour commenter.

Réponse acceptée

Titus Edelhofer
Titus Edelhofer le 31 Août 2018
Hi Nils,
I didn't take a look into the zip file but could it be that you did the same mistake as I, namely, really passing a string ("hello") to the S-function instead of the char array ('hello')? If I use the string class, then I see the same problem. When passing an old fashioned char array, then everything works as expected.
Titus
  3 commentaires
Nils Gerke
Nils Gerke le 31 Août 2018
That did the trick, I marked your answer as accepted. But never the less I would suspect
mxArrayToString()
to be able to process string input as well as char array input. If this is not possible it would be nice to throw a proper exception. Now all that happens is that MATLAB crashes with a Fatal Exception.
Titus Edelhofer
Titus Edelhofer le 31 Août 2018
Yes and no: yes, the fatal exception is indeed "undesirable" :). And yes again: would be good if the function also accepts strings and not only char arrays. Now for the no: this is the C world, and it's (unfortunately?) the users responsibility to check return values.
It's the further processing of the NULL pointer that causes the exception. In the doc you see:
Returns C-style string. Returns NULL on failure. Possible reasons for failure include out of memory and specifying an array that is not an mxCHAR array.
Titus

Connectez-vous pour commenter.

Plus de réponses (1)

Titus Edelhofer
Titus Edelhofer le 30 Août 2018
Hi Nils,
just to be sure: did you check the number of parameters you passed? I guess you are sure that there is at least one parameter, but may helps to check, because otherwise it looks fine. Try
int nParam = ssGetSFcnParamsCount(S);
mexPrintf("Number of parameters: %d\n", nParam);
Titus
  5 commentaires
Titus Edelhofer
Titus Edelhofer le 31 Août 2018
O.K., then I guess we need to wait to see a reproducing example ...
Nils Gerke
Nils Gerke le 31 Août 2018
I added a reproducing example, see code and .zip of post 1

Connectez-vous pour commenter.

Produits


Version

R2018a

Community Treasure Hunt

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

Start Hunting!

Translated by