Ccaffeine Reference Framework for CCA Components | ||
---|---|---|
<<< Previous | PortTranslator: A Babel gov.cca.Port that provides access to the Ccaffeiene Classic Type Components |
Follow the procedures outlined here to use the PortTranslator port unless you are absolutely sure what you are doing. |
Since the only way to get foreign objects into and out of the SIDL/Bable world is to use the SIDL opaque type, certain non-obvious procedures must be observed in the C++ use of the SIDL/Babel PortTranslator. This is necessary because of two independent but, for the programmer, interacting things:
SIDL/Babel opaque is mapped tovoid *.
C++ cast's are not unique or commutative. That is: (PortTranslator*)(void*)(Port*) != (PortTranslator*)(Port*)(void*).
Ultimately, the thing to keep in mind is that PortTranslator expects and returns void* that are always cast from the type classic::gov::cca::Port* and must be static_cast'ed back to that type before anything else is done. A full example is built with the Ccaffeine distribution and can be found in $CCAFE_ROOT/cxx/dc/babel/component/PortTranslatorStarter. The following is an excerpt from that component that illustrates how to import and export Classic ports in the Babel religion:
/**
* Obtain Services handle, through which the
* component communicates with the framework.
* This is the one method that every CCA Component
* must implement.
*/
void
ccafe_eg::PortTranslatorStarter_impl::setServices (
/*in*/ gov::cca::Services services )
throw ()
{
// DO-NOT-DELETE splicer.begin(ccafe_eg.PortTranslatorStarter.setServices)
svc = services;
try {
/** Check to see if we are alive or dead. */
if(services._not_nil()) {
gov::cca::TypeMap tm = svc.createTypeMap(); // nil TypeMap
gov::cca::ports::GoPort gp = self;
svc.addProvidesPort(gp, std::string("go"),
std::string("gov.cca.ports.GoPort"), tm);
// We register for a plain old StringConsumerPort, this is a
// Classic port that will (hopefully) be connected to us.
svc.registerUsesPort(std::string("classicOut"),
std::string("StringConsumerPort"), tm);
// We register this guy in the normal way for the Babel religion.
svc.registerUsesPort(std::string("babelOut"),
std::string("ccafe0.StringConsumerPort"), tm);
// Now for parameters. We do the full enchalada here, dynamic
// parameters included. Dynamic parameters call back on this
// class to tell the component that the parameters have changed.
// This is appropriately harder to accomplish than simple static
// parameters. Note that static parameters will *change*
// dynamically when changed in the GUI, they just won't notify
// you of the change, at the time the change happens.
// Here we fish out the Service provided by Ccaffeine to do
// dynamic parameters.
svc.registerUsesPort("classicParam",
"gov.cca.ParameterPortFactoryService", tm);
// Since it is a Service, we can get it right away.
gov::cca::Port p = svc.getPort("classicParam");
// Since it is a classic service it comes in a PortTranslator
// package, which we must cast down from gov::cca::Port, using
// (sigh) the "=" operator.
ccaffeine::ports::PortTranslator portX = p; //cast
// Since I almost never make mistakes, but I hear others do, it
// is good to check to see that the cast succeeded.
if(portX._not_nil()) {
// Here we use the getClassicPort() method on PortTranslator
// that must always be casted blindly to a
// classic::gov::cca::Port* and absolutely nothing else.
classic::gov::cca::Port * cp =
static_cast < classic::gov::cca::Port * > (portX.getClassicPort());
if(cp == NULL) { // icky.
fprintf(stderr, ":-( the port returned is not one of "
"classic::gov::cca::Port or is NULL\n");
return;
}
// Now we do the dynamic_cast down to the specific
// classic::gov::cca::Port: ConfigurableParameterFactory that
// will help us do dynamic parameters.
ConfigurableParameterFactory *cpf =
dynamic_cast < ConfigurableParameterFactory * > (cp);
// Now we get the parameters set up in another routine.
ConfigurableParameterPort *pp = setupParameters(cpf);
// Now we begin the process of adding a classic port to this
// component: the parameter port that GUI users can click on
// and configure.
// First we *must* get it into the type that the
// PortTranslator is expecting: cast it to a
// classic::gov::cca::Port*.
classic::gov::cca::Port * clscp =
dynamic_cast < classic::gov::cca::Port * > (pp);
if(clscp == NULL) {
fprintf(stderr, "Something went wrong with the ParameterPort "
"returned from setupParameters\n");
}
// Next pass it to PortTranslator by createFromClassic(void*)
void * vp = static_cast < void * > (clscp);
ccaffeine::ports::PortTranslator provideX =
ccaffeine::ports::PortTranslator::createFromClassic(vp);
// Add the configure port that we want to provide.
svc.addProvidesPort(provideX, "configure", "ParameterPort", tm);
// Let go of the ParameterPortFactoryService we got previously.
svc.releasePort("classicParam");
svc.unregisterUsesPort("classicParam");
}
}
} catch(std::exception & e) {
fprintf(stderr, "Exception caught: %s\n", e.what());
}
// DO-NOT-DELETE splicer.end(ccafe_eg.PortTranslatorStarter.setServices)
}
<<< Previous | Home | |
PortTranslator: A Babel gov.cca.Port that provides access to the Ccaffeiene Classic Type Components | Up |