Simulink mex s-function: rename in/output port from c-code?

Hi
I'm struggeling with a problem: to rename scalar in/output signals of a custom mex-s-function block during initialization time (mdlInitializeSize() for example).
Is this possible? I tried several hacks so far, but got nothing but a bunch of MATLAB crashes... alas, we reached 2012, so at least web2.0 has to be good for something ;-)
My first try was to execute normal matlab code from the C-side using mexEvalString(). So something equivalent to:
p = get_param(gcb, 'PortHandles')
l = get_param(p.Outport, 'Line')
set_param(l, 'Name', 'myname')
But the "gcb" statement may choose some other blocks, and not always the block where the C-code is residing in... Is there some other possibility to access the current S-Function block at this stage?
In the documentation I found the suggestion to be at least able to check the name of an "Bus Port" (and only after certain things are applied, so this just may go in a kind of right direction and not solve my problem):
DTypeId dType = ssGetOutputPortDataType(S, 0);
int numElems = ssGetNumBusElements(S, dType);
const char *elemName = (char*)ssGetBusElementName(S, dType, 0);
std::cout << elemName << std::endl;
...which will crash during execution. probably because i dont have a bus but a single port... Since I found no field named "name" or typed "char*" in the SimStruct*-argument i suppose there is no such information on the C-side.
Whatever. Do you pros have an idea what I could or should do?
Thanks a lot!

 Accepted Answer

More Answers (1)

Hm, thanks for the idea... ssGetPath returns the path to the block as a string. nice. after making some mistakes (have to edit my complete answer...) i figured out how this works. "find_system" is the wrong call to get the handle, "get_param('bla','Handle')" does this. So my complete code looks like this:
h = get_param('modell/helloworld', 'Handle')
p = get_param(h, 'PortHandles')
l = get_param(p.Outport, 'Line')
set_param(l, 'Name', 'myname')
so now let's say I have more than one output port to work on: then the last call to "get_param()" will return a cell-array... I can't squeeze everything in one line.
is there an obvious way to code this in C? I one solution would be to use several calls to "mexCallMATLAB()" to prevent cluttering of users worksspace... however this is much coding work ;-) The other would be to rely on variables in the MATLAB workspace and code this as a "poor-mans-m-script"...
edit again: yay it works... but i have to say: i hate plain c... i probably leaked more memory than i allocated...
last edit: for the sake of completeness and for educational purposes, here my CC-BY-SA'ed over-verbose memory leaking solution:
/* this is an awfull lot of c-code... which does essentially the same as the following:
* at first (only possible/neccessary on the c-side) getting the block-path of _this_ block
path = ssGetPath(S);
* then setting the name after obtaining the correct data-structures. the corresponding m-code is as
* follows:
h = get_param(path, 'Handle')
p = get_param(h, 'PortHandles')
l = get_param(p.Outport, 'Line')
set_param(l(portId+1), 'Name',name)
* note that this only works error-less if the port is connected!
*/
bool setOutputPortName(SimStruct* S, unsigned int portNr, const char* name)
{
/* at first get the handle to our simulink function block */
mxArray* h;
{
mxArray *right[2];
right[0] = mxCreateString(ssGetPath(S));
right[1] = mxCreateString("Handle");
mexCallMATLAB(1,&h,2,right,"get_param");
mxDestroyArray(right[0]);
mxDestroyArray(right[1]);
}
mxArray* p;
/* now obtain the 'PortHandles' struct-field "Outport" of the given port-id... */
{
mxArray *left[1];
mxArray *right[2];
right[0] = h;
right[1] = mxCreateString("PortHandles");
mexCallMATLAB(1,left,2,right,"get_param");
mxDestroyArray(h);
mxDestroyArray(right[1]);
/* get string inside a struct-field named "Outport" */
if (!mxIsStruct(left[0]))
{
std::cerr << "setOutputPortName() no stuct returned" << std::endl;
return false;
}
/* in field "field_num", there resides an array with all Outport-handles. we need the one
* indexd by "portNr" */
mxArray* temp = mxGetField(left[0], 0, "Outport");
p = mxCreateDoubleScalar(mxGetPr(temp)[portNr]);
/* i am allowed to destroy the return-array myself */
mxDestroyArray(left[0]);
}
/* finally we have to get the last param "Line" */
mxArray* l;
{
mxArray *right[2];
right[0] = p;
right[1] = mxCreateString("Line");
mexCallMATLAB(1,&l,2,right,"get_param");
mxDestroyArray(p);
mxDestroyArray(right[1]);
}
/* and now, we can set out payload, finally... i hate plain-c */
{
mxArray *right[3];
right[0] = l;
right[1] = mxCreateString("Name");
right[2] = mxCreateString(name);
mexCallMATLAB(0,NULL,3,right,"set_param");
mxDestroyArray(l);
mxDestroyArray(right[1]);
mxDestroyArray(right[2]);
}
}

Community Treasure Hunt

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

Start Hunting!