Modeling Services > Dynamic Modeling Services > How to Use Dynamic Objects > Dynamic Member Functions
 
Dynamic Member Functions
You can assign a C++ function to a method that has been declared dynamically. To do so, use the API of the server model interpreter. (See the static member function IlsModelInterpreter::DeclFunImplementation.)
If a dynamic method has not been assigned a C++ function, Rogue Wave® Server will search for a matching Rogue Wave® Script function whose name is built from the class name and the method name. For example, if you have a dynamic method named display for the class Network, Rogue Wave Server will search for the Rogue Wave Script function Network_display(network). From C++ code, you can use the member function IlsDynObject::callFunction to invoke the dynamic member function. Unlike standard member functions declared using the ILS_MEMBER_FUNCTION macros, dynamic member functions can reference Server types in their list of arguments. In this case, they must be used only from scripts or from the IlsDynObject::callFunction API. To declare such a member function in your C++ classes, you must use the macros ILS_SV_MEMBER_FUNCTION instead of the standard ILS_MEMBER_FUNCTION macros. When passed to the method implementation, the Server-type arguments are encapsulated in an IlsMvValue of type IlsSvRef, from which you can retrieve a pointer to the server object.
Figure 5.2    Dynamic Member Function
Note that in such a case, the method should not be called from a component through an execCallback nor used in a dynamic view specification, but can be invoked from a script. See “Implementing Dynamic Functions Using Scripts”. for more information.
The Rogue Wave Script integration has access to all member functions declared with ILS_MEMBER_FUNCTION macros and to all member functions declared with the ILS_SV_MEMBER_FUNCTION macros, as well as to all member functions declared through the dynamic model interpreter API and the XMI parser.
Example
Let us consider the following model:
Figure 5.3    Dynamic Member Function with Server Type
Assuming that this class is implemented as a C++ class, the getFirstFlightFrom function must be declared with the following macro:
ILS_SV_MEMBER_FUNCTION1(Flight, Airport, getFirstFlightFrom, Airport)
The code is the following:
IlsMvValue
Airport::getFirstFlightFrom(IlsMvValue arg)
{
Airport* fromAirport = 0;
if (arg.isSvRef()) {
IlsSvRef r = arg.asSvObjectRef();
fromAirport =(Airport*)r.getObject();
}
 
if (fromAirport) {
IlsInvertedRelationList<Airport, Flight>::Iterator i(arrivals);
Flight* f;
while (i>>f) {
if (f->from == fromAirport)
return IlsSvRef(f, "Flight");
}
}
return IlsSvRef();
}
And this method can be invoked from a script, like this:
function f{) {
var sydney = MvServer.GetInstance("Airport", "Sydney");
var paris = MvServer.GetInstance("Airport", "Paris");
var f = sydney.getFirstFlightFrom(paris);
}
Virtuality
If you choose to work with Rogue Wave Server dynamic modeling services, you should proceed with caution when mixing JavaScriptTM and C++ methods with regard to calling virtual methods. Overriding a virtual C++ method in JavaScript works only if this method is called from a JavaScript method or through the function IlsDynObject::callFunction.
For example, an instance b of class B which calls the method cpp_call inherited from class A should call the overridden method f in class B. But the C++ mechanism for virtual methods does not know of this script method and calls the C++ function A::f.
In this same example, calling the JavaScript method script_call inherited from class A results in calling the overridden method b in class B as expected.
The only way to be sure to call the right virtual method is to use the Server virtual mechanism for function calls. Thus, the implementation of the C++ method in this example should be:
void cpp_call() {Callfunction("f"); }
Example
class A {
void cpp_call() { f(); }
script function script_call() { f(); }
virtual void f() { cout << "A::f()"; }
}
 
class B : A {
script function f() { cout << "B::f()"; }
}
 
 
var b = new B();
b.cpp_call(); // prints A::f();
b.script_call(); // prints B::f();
Remark
Let us suppose that:
*A C++ class BaseNetwork (inheriting from IlsDynObject) declares a C++ member function named display.
*A dynamic class Network defined in XMI also declares a display method.
In this case, when the method execCallback is called on a representation object of the class Network on the component side, the implementation of the method Network::display will be invoked. If the class Network does not declare the method display in XMI, then the C++ method will be called.

Version 5.8
Copyright © 2014, Rogue Wave Software, Inc. All Rights Reserved.