Discussion:
C MEX S-Function Builder
(too old to reply)
Cahit
2006-09-11 15:34:47 UTC
Permalink
Hi all,

In my simulink model, to split a double value into 8 uint8 values, i
am trying to integrate a simple C Code into an S-function! It's
neither continous nor discrete case.

In my model, block order is :

constant double x--> S-Function --> Display

For that, i am using S-Function Builder and giving all datas what it
needs but if i want to build this, it gives me no reaction, nothing
happens!

My C Code is,

int transmit (double x,unsigned int y);


int transmit (double x, unsigned int y)

{

union ifas { double d;unsigned char u[8];};

union ifas member;

member.d = x ;
member.u[8] = y;

return y;

}

I also give the header files iostream.h, stdio.h etc in builder
Dialog box. I do not understand what is wrong?

Anyone who worked on such things before, i appreciate your
suggestions really. Thanks in advance!

Cheers,
Cahit
Praetorian
2006-09-11 16:01:41 UTC
Permalink
Post by Cahit
Hi all,
In my simulink model, to split a double value into 8 uint8 values, i
am trying to integrate a simple C Code into an S-function! It's
neither continous nor discrete case.
constant double x--> S-Function --> Display
For that, i am using S-Function Builder and giving all datas what it
needs but if i want to build this, it gives me no reaction, nothing
happens!
My C Code is,
int transmit (double x,unsigned int y);
int transmit (double x, unsigned int y)
{
union ifas { double d;unsigned char u[8];};
union ifas member;
member.d = x ;
member.u[8] = y;
return y;
}
I also give the header files iostream.h, stdio.h etc in builder
Dialog box. I do not understand what is wrong?
Anyone who worked on such things before, i appreciate your
suggestions really. Thanks in advance!
Cheers,
Cahit
Cahit, you will need a for loop to assign the 8 uint8 values to your
output variable. Also, assuming 'y' is your output variable your
assignment is wrong. Shouldn't it read

y[i] = member.u[i];

Another thing you need to make sure is that your compiler does support
chars. You can use ssPrintf to print out sizeof(unsigned char) and
sizeof(unsigned short), they should be 1 and 2 respectively. If it
doesn't you'll have to use unsigned shorts and do some shifting or else
use bit fields if those are supported.

If you could copy-paste your mdlInitializeSizes and mdlOutputs
functions I can help you out more with this problem.

HTH,
Ashish.
Cahit
2006-09-12 17:41:33 UTC
Permalink
Post by Cahit
Post by Cahit
Hi all,
In my simulink model, to split a double value into 8 uint8
values, i
Post by Cahit
am trying to integrate a simple C Code into an S-function! It's
neither continous nor discrete case.
constant double x--> S-Function --> Display
For that, i am using S-Function Builder and giving all datas
what
Post by Cahit
it
Post by Cahit
needs but if i want to build this, it gives me no reaction,
nothing
Post by Cahit
happens!
My C Code is,
int transmit (double x,unsigned int y);
int transmit (double x, unsigned int y)
{
union ifas { double d;unsigned char u[8];};
union ifas member;
member.d = x ;
member.u[8] = y;
return y;
}
I also give the header files iostream.h, stdio.h etc in builder
Dialog box. I do not understand what is wrong?
Anyone who worked on such things before, i appreciate your
suggestions really. Thanks in advance!
Cheers,
Cahit
Cahit, you will need a for loop to assign the 8 uint8 values to your
output variable. Also, assuming 'y' is your output variable your
assignment is wrong. Shouldn't it read
y[i] = member.u[i];
Another thing you need to make sure is that your compiler does
support
chars. You can use ssPrintf to print out sizeof(unsigned char) and
sizeof(unsigned short), they should be 1 and 2 respectively. If it
doesn't you'll have to use unsigned shorts and do some shifting or else
use bit fields if those are supported.
If you could copy-paste your mdlInitializeSizes and mdlOutputs
functions I can help you out more with this problem.
HTH,
Ashish.
Hello Ashish,

I really want to thank you in advance for your consideration.
Yes, in your last message you were right, i made a mistake about
assignment of y.Now here is my actual C Code:

void double2integer(double x, unsigned char *y)
{
int i;

union ifas{double d; unsigned char uvalue[8];};
union ifas var;

var.d = x;

for (i=0 ; i<8 ; i++)
{
y[i]=var.uvalue[i];
}

}

int main()
{
unsigned char number[8];
double variable;
double2integer(variable,number);
return 0;
}

And then i just tried this code to adapt to Simulink S-Function. For
this purpose, i took one of C S-Function Templates from simulink/src
file, namely timestwo.c as an example!
It is actually hard for me to adapt this code as template has macros
used with pointers which confuse me.Therefore, i have things about
which i am really concerned.

static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;}

ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);

if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
ssSetInputPortDirectFeedThrough(S, 0, 1);

if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
// ATTENTION : OutputPortWidth, should i leave it like this
(Dynamically Sized) or submit [8 1] as we expect 8 set of usign8
array?

ssSetNumSampleTimes(S, 1);

/* Take care when specifying exception free code - see
sfuntmpl_doc.c */
ssSetOptions(S,
SS_OPTION_WORKS_WITH_CODE_REUSE |
SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_USE_TLC_WITH_ACCELERATOR);
}

My mdlOutputs Function:

static void mdlOutputs(SimStruct *S, int_T tid)

{
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);

real_T *y = ssGetOutputPortRealSignal(S,0);
int_T width = ssGetOutputPortWidth(S,0);

// ATTENTION : Again width here.


union ifas { double d ; unsigned char uvalue[8] ; } ;

union ifas var;

var.d = *uPtrs[i];

for (i=0; i<8; i++) // width = 8
{
*y[i]=var.uvalue[i];
}

}

Here, as help menu says, *uPtrs[i] is to access input datas and
similarly *y for output.How about the 'main' function in original C
Code?

To be honest, i could not have time to check it whether it is working
as i have to leave the work now but still wanted to send you to save
time because of time difference. I of course strongly appreciate what
you think or suggest about my code. Thank you very much.

Regards,
Cahit
Praetorian
2006-09-12 19:14:20 UTC
Permalink
Post by Cahit
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;}
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
If you just want to accept an input of width one you should use
ssSetInputPortWidth(S, 0, 1);

Also use ssSetInputPortDataType(S, 0, SS_DOUBLE);
Post by Cahit
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
Similarly, if you set input port width to 1 above you should set output
port width to 8. And specify
ssSetOutputPortDataType(S, 0, SS_UINT8);
Post by Cahit
// ATTENTION : OutputPortWidth, should i leave it like this
(Dynamically Sized) or submit [8 1] as we expect 8 set of usign8
array?
ssSetNumSampleTimes(S, 1);
/* Take care when specifying exception free code - see
sfuntmpl_doc.c */
ssSetOptions(S,
SS_OPTION_WORKS_WITH_CODE_REUSE |
SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_USE_TLC_WITH_ACCELERATOR);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
I would use this instead

uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
Post by Cahit
int_T width = ssGetOutputPortWidth(S,0);
// ATTENTION : Again width here.
union ifas { double d ; unsigned char uvalue[8] ; } ;
union ifas var;
var.d = *uPtrs[i];
for (i=0; i<8; i++) // width = 8
{
*y[i]=var.uvalue[i];
}
}
You don't really need a union"

int_T i;
for(i=0; i<width; i++) {
InputUint8PtrsType uPtrs =
(InputUint8PtrsType)ssGetInputPortSignalPtrs(S,0);
*y[i] = *uPtrs[i];
}
Post by Cahit
Here, as help menu says, *uPtrs[i] is to access input datas and
similarly *y for output.How about the 'main' function in original C
Code?
To be honest, i could not have time to check it whether it is working
as i have to leave the work now but still wanted to send you to save
time because of time difference. I of course strongly appreciate what
you think or suggest about my code. Thank you very much.
Regards,
Cahit
If you do use the DYNAMICALLY_SIZED option then you'll have to add the
following routine

# define MDL_SET_INPUT_PORT_WIDTH
static void mdlSetInputPortWidth(SimStruct *S, int_T port, int_T
inputPortWidth)
{
ssSetInputPortWidth(S,port,inputPortWidth);
ssSetOutputPortWidth(S,port,inputPortWidth*8);
}

HTH,
Ashish.
Cahit
2006-09-13 15:46:24 UTC
Permalink
Post by Praetorian
Post by Cahit
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;}
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, DYNAMICALLY_SIZED);
If you just want to accept an input of width one you should use
ssSetInputPortWidth(S, 0, 1);
Also use ssSetInputPortDataType(S, 0, SS_DOUBLE);
Post by Cahit
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, DYNAMICALLY_SIZED);
Similarly, if you set input port width to 1 above you should set output
port width to 8. And specify
ssSetOutputPortDataType(S, 0, SS_UINT8);
Post by Cahit
// ATTENTION : OutputPortWidth, should i leave it like this
(Dynamically Sized) or submit [8 1] as we expect 8 set of
usign8
Post by Praetorian
Post by Cahit
array?
ssSetNumSampleTimes(S, 1);
/* Take care when specifying exception free code - see
sfuntmpl_doc.c */
ssSetOptions(S,
SS_OPTION_WORKS_WITH_CODE_REUSE |
SS_OPTION_EXCEPTION_FREE_CODE |
SS_OPTION_USE_TLC_WITH_ACCELERATOR);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
InputRealPtrsType uPtrs = ssGetInputPortRealSignalPtrs(S,0);
real_T *y = ssGetOutputPortRealSignal(S,0);
I would use this instead
uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
Post by Cahit
int_T width = ssGetOutputPortWidth(S,0);
// ATTENTION : Again width here.
union ifas { double d ; unsigned char uvalue[8] ; } ;
union ifas var;
var.d = *uPtrs[i];
for (i=0; i<8; i++) // width = 8
{
*y[i]=var.uvalue[i];
}
}
You don't really need a union"
int_T i;
for(i=0; i<width; i++) {
InputUint8PtrsType uPtrs =
(InputUint8PtrsType)ssGetInputPortSignalPtrs(S,0);
*y[i] = *uPtrs[i];
}
Post by Cahit
Here, as help menu says, *uPtrs[i] is to access input datas and
similarly *y for output.How about the 'main' function in
original
Post by Praetorian
C
Post by Cahit
Code?
To be honest, i could not have time to check it whether it is
working
Post by Cahit
as i have to leave the work now but still wanted to send you to
save
Post by Cahit
time because of time difference. I of course strongly
appreciate
Post by Praetorian
what
Post by Cahit
you think or suggest about my code. Thank you very much.
Regards,
Cahit
If you do use the DYNAMICALLY_SIZED option then you'll have to add the
following routine
# define MDL_SET_INPUT_PORT_WIDTH
static void mdlSetInputPortWidth(SimStruct *S, int_T port, int_T
inputPortWidth)
{
ssSetInputPortWidth(S,port,inputPortWidth);
ssSetOutputPortWidth(S,port,inputPortWidth*8);
}
HTH,
Ashish.
Hi Ashish again,

Thanks for your suggestions, i think i have just one step to the
target, i compiled this following code and tried in a simple model
but gives me 8 times first uninteger value instead of desired matrix
below, e.g. double value=pi, my output is 8 times 24 which is the
first value of uint8 array.

[24 45 68 84 251 33 9 64]

Here is my actual code again :

static void mdlInitializeSizes(SimStruct *S)

{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}

ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);

if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortDirectFeedThrough(S, 0, 1);

if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 8);
ssSetOutputPortDataType(S, 0, SS_UINT8);

ssSetNumSampleTimes(S, 1);

ssSetOptions(S,0);
}

static void mdlOutputs(SimStruct *S, int_T tid)

{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);

InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);

uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
InputUInt8PtrsType pU0 = (InputUInt8PtrsType)uPtrs;

for(i=0; i<width; i++)

{
y[i] = *pU0[i];
}

}

Main thing is outputmdl function i think, what should i change to get
the desired matrix? i just played around with the pointers, when i
say,

*y[i] = *pU0[i];

compiler gives me error.

I would be very pleased if you could refer also to this issue.Thank
you.

Regards,
Cahit
Praetorian
2006-09-13 19:30:44 UTC
Permalink
Post by Cahit
Hi Ashish again,
Thanks for your suggestions, i think i have just one step to the
target, i compiled this following code and tried in a simple model
but gives me 8 times first uninteger value instead of desired matrix
below, e.g. double value=pi, my output is 8 times 24 which is the
first value of uint8 array.
[24 45 68 84 251 33 9 64]
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 8);
ssSetOutputPortDataType(S, 0, SS_UINT8);
ssSetNumSampleTimes(S, 1);
ssSetOptions(S,0);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);
InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);
uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
InputUInt8PtrsType pU0 = (InputUInt8PtrsType)uPtrs;
for(i=0; i<width; i++)
{
y[i] = *pU0[i];
}
}
Main thing is outputmdl function i think, what should i change to get
the desired matrix? i just played around with the pointers, when i
say,
*y[i] = *pU0[i];
compiler gives me error.
I would be very pleased if you could refer also to this issue.Thank
you.
Regards,
Cahit
Cahit, the code correct to me, I have no idea why it's not working.

*y[i] = *pU0[i];

That assignment is wrong because you're trying to assign the input
value to a pointer to the output pointer and that's why the compiler
complained.

Try the mdlOutputs code with the union you had before and see it that
works.

Also, you can try printing out things like *pu0[0], *pu0[1], *pu0[2],
*pu0[3], *pu0[4], *pu0[5], *pu0[6], *pu0[7] inside mdlOutputs in the
above code using ssPrintf for debugging. If you're using MS Visual C++
pro for compiling your C S-Function then there's even a way to
breakpoint in the file and watch variables. Look in the help
documentation for this.

HTH,
Ashish.
Cahit
2006-09-14 12:16:37 UTC
Permalink
Post by Cahit
Post by Cahit
Hi Ashish again,
Thanks for your suggestions, i think i have just one step to
the
Post by Cahit
Post by Cahit
target, i compiled this following code and tried in a simple
model
Post by Cahit
but gives me 8 times first uninteger value instead of desired
matrix
Post by Cahit
below, e.g. double value=pi, my output is 8 times 24 which is
the
Post by Cahit
Post by Cahit
first value of uint8 array.
[24 45 68 84 251 33 9 64]
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
if (!ssSetNumInputPorts(S, 1)) return;
ssSetInputPortWidth(S, 0, 1);
ssSetInputPortDataType(S, 0, SS_DOUBLE);
ssSetInputPortDirectFeedThrough(S, 0, 1);
if (!ssSetNumOutputPorts(S,1)) return;
ssSetOutputPortWidth(S, 0, 8);
ssSetOutputPortDataType(S, 0, SS_UINT8);
ssSetNumSampleTimes(S, 1);
ssSetOptions(S,0);
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);
InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);
uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
InputUInt8PtrsType pU0 = (InputUInt8PtrsType)uPtrs;
for(i=0; i<width; i++)
{
y[i] = *pU0[i];
}
}
Main thing is outputmdl function i think, what should i change
to
Post by Cahit
get
Post by Cahit
the desired matrix? i just played around with the pointers,
when
Post by Cahit
i
Post by Cahit
say,
*y[i] = *pU0[i];
compiler gives me error.
I would be very pleased if you could refer also to this
issue.Thank
Post by Cahit
you.
Regards,
Cahit
Cahit, the code correct to me, I have no idea why it's not working.
*y[i] = *pU0[i];
That assignment is wrong because you're trying to assign the input
value to a pointer to the output pointer and that's why the
compiler
complained.
Try the mdlOutputs code with the union you had before and see it that
works.
Also, you can try printing out things like *pu0[0], *pu0[1],
*pu0[2],
*pu0[3], *pu0[4], *pu0[5], *pu0[6], *pu0[7] inside mdlOutputs in the
above code using ssPrintf for debugging. If you're using MS Visual C++
pro for compiling your C S-Function then there's even a way to
breakpoint in the file and watch variables. Look in the help
documentation for this.
HTH,
Ashish.
Hello Ashish,

Many thanks for your reply.I also do not understand what is going
wrong and about to go mad really. Anyway, i tried to use union once
more:

Just before initialization function,

typedef union { uint8_T uvalue[8];
real_T d;
} UnionNum;

static void mdlOutputs(SimStruct *S, int_T tid)

{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);

InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);

uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
UnionNum num;
num.d = uPtrs ;

for(i=0; i<width; i++)
{
y[i] = num.uvalue[i];

}
}
Post by Cahit
Post by Cahit
mex double2integer.c
Error double2integer.c: 79 operands of = have illegal types `double'
and `pointer to const pointer to const void'

Why does it have problem with 'double'? Do you see anything to
correct here? I appreciate your help again. Thank you.

Regards,
Cahit
Praetorian
2006-09-14 14:52:28 UTC
Permalink
Post by Cahit
Hello Ashish,
Many thanks for your reply.I also do not understand what is going
wrong and about to go mad really. Anyway, i tried to use union once
Just before initialization function,
typedef union { uint8_T uvalue[8];
real_T d;
} UnionNum;
static void mdlOutputs(SimStruct *S, int_T tid)
{
int_T i;
int_T width = ssGetOutputPortWidth(S,0);
InputPtrsType uPtrs = ssGetInputPortSignalPtrs(S,0);
uint8_T *y = (uint8_T *)ssGetOutputPortSignal(S,0);
UnionNum num;
num.d = uPtrs ;
This is incorrect, the assignment shoult be:

num.d = *uPtrs[0];

uPtrs is a pointer to a pointer to the input so you cannot assign it
directly to a double.

Also try adding this line for debugging:

ssPrintf("sizeof union = %d\n",sizeof(num));

If the value printed is greater than 8 that means your machine doesn't
support a uint8s and so uint8_T is actually something larger. In that
case you'll have to do some bitwise AND and shifting math to get your
result.
Post by Cahit
for(i=0; i<width; i++)
{
y[i] = num.uvalue[i];
}
}
Post by Cahit
mex double2integer.c
Error double2integer.c: 79 operands of = have illegal types `double'
and `pointer to const pointer to const void'
Why does it have problem with 'double'? Do you see anything to
correct here? I appreciate your help again. Thank you.
Regards,
Cahit
HTH,
Ashish.

Loading...