The next step is to get Babel to generate the skeleton code that
we will fill in with the component's implementation. In the
directory, type $STUDENT_SRC/componentsmake
.drivers.CXXDriver-cxx. The output should look
something like this:
### Generating a cxx implementation for the drivers.CXXDriver component.
/san/cca/cca-tools_gcc_intelF90_PIC/bin/babel -s cxx -R../xml_repository \
-R/san/cca/cca-tools_gcc_intelF90_PIC/share/cca-spec-babel-0_7_8-babel-0.10.10/xml \
-g -u -E -l -m drivers.CXXDriver. --suppress-timestamp drivers.CXXDriver
Babel: Resolved symbol "drivers.CXXDriver"...
touch .drivers.CXXDriver-cxx
and in the
directory, you should see the following files:
$STUDENT_SRC/components/drivers/cxx
drivers.CXXDriver.babel.make drivers_CXXDriver_Impl.cxx drivers_CXXDriver_Impl.hxx glue
all of which were generated by Babel. (glue is actually a directory that
contains a large number of generated files that Babel needs to do
its job, but which you never need to modify.) The source code
files that you will need to modify in order to implement the
component are the so-called Impl files. For C++, both a source
file (.cxx) and the
corresponding header file (.hxx) are generated.
In your editor, take a look through both
and
$STUDENT_SRC/components/drivers/cxx/drivers_CXXDriver_Impl.cxx
to familiarize yourself with their structure before you make any
changes.
$STUDENT_SRC/components/drivers/cxx/drivers_CXXDriver_Impl.hxx
Near the top of drivers_CXXDriver_Impl.hxx,
you will see a group of include directives:
... // // Includes for all method dependencies. // #ifndef included_drivers_CXXDriver_hxx #include "drivers_CXXDriver.hxx" #endif ...
Babel generates include directives for header
files that are necessary to resolve the types used in the SIDL
definition of the class you're implementing (in this case, in
the
file). It does not automatically generate
include directives for interfaces you
implement. You will have to add those and any
other header files your implementation requires as part of the
implementation process.
$STUDENT_SRC/components/sidl/drivers.sidl
When an automatically generated file is manually modified, there is always a danger that the modifications will be overwritten the next time the file is generated. Babel solves this with a concept called splicer blocks. These structured comments that appear to the compiler as regular comments, but are interpreted by Babel as having a special meaning. Babel will preserve code within a splicer block when the file is regenerated. Code outside splicer blocks will be overwritten. Most Babel-generated files contain numerous splicer blocks -- everywhere you might need to add something to the generated skeleton. Here is an example:
... // DO-NOT-DELETE splicer.begin(drivers.CXXDriver._includes) // Put additional includes or other arbitrary code here... // DO-NOT-DELETE splicer.end(drivers.CXXDriver._includes) ...
Note that each splicer block has a name that is unique within the file, and has explicit beginning and end markers. In this case, the leading comment syntax is appropriate to C++, but of course files generated for other languages will have different ways of denoting comments.
In the drivers_CXXDriver_Impl.cxx, You will
see that Babel has already generated the signatures for all of
the methods you need to implement, giving them appropriate
C++-ized names, and has provided splicer blocks ready for you to
fill in (with a default method body that throws a "method not
implemented" exception). This includes both the go
method inherited from the
gov.cca.ports.GoPort definition,
and the setServices method inherited
from the gov.cca.Component
definition. You will obviously need to delete the babel-generated
code that throws the exception (or comment it out), and replace it
with the code that actually implements the method under consideration.
We'll begin by implementing the
setServices method in
drivers_CXXDriver_Impl.cxx. Here is what
the routine should look like (you'll need to type in the stuff
marked up like this), along with some
comments about different sections.
... /** * Method: setServices[] */ void drivers::CXXDriver_impl::setServices ( /*in*/ ::gov::cca::Services services ) throw ( ::gov::cca::CCAException ){ // DO-NOT-DELETE splicer.begin(drivers.CXXDriver.setServices) // insert implementation hereframeworkServices = services;// Provide a Go port gov::cca::ports::GoPort gp = (*this);
frameworkServices.addProvidesPort(gp,
![]()
"GoPort", "gov.cca.ports.GoPort", frameworkServices.createTypeMap()); // Use an IntegratorPort port frameworkServices.registerUsesPort ("IntegratorPort",// DO-NOT-DELETE splicer.end(drivers.CXXDriver.setServices) } ..."integrator.IntegratorPort", frameworkServices.createTypeMap());
The header file also requires a couple of additions. First, let's
take care of declaring frameworkServices as a
private variable belonging to the
drivers::CXXDriver class.
Edit
and add the following:
$STUDENT_SRC/components/drivers/cxx/drivers_CXXDriver_Impl.hxx
...
/**
* Symbol "drivers.CXXDriver" (version 1.0)
*/
class CXXDriver_impl : public virtual ::drivers::CXXDriver
// DO-NOT-DELETE splicer.begin(drivers.CXXDriver._inherits)
// Insert-Code-Here {drivers.CXXDriver._inherits} (optional inheritance here)
// DO-NOT-DELETE splicer.end(drivers.CXXDriver._inherits)
{
// All data marked protected will be accessable by
// descendant Impl classes
protected:
bool _wrapped;
// DO-NOT-DELETE splicer.begin(drivers.CXXDriver._implementation)
// Insert-Code-Here {drivers.CXXDriver._implementation} (additional details)
::gov::cca::Services frameworkServices;
// DO-NOT-DELETE splicer.end(drivers.CXXDriver._implementation)
...
We also need to add the include directives for the header files for the classes we inherit from. (For technical reasons, Babel does not insert these automatically when it generates the file.)
...
// DO-NOT-DELETE splicer.begin(drivers.CXXDriver._includes)
// Put additional includes or other arbitrary code here...
#include "integrator_IntegratorPort.hxx"
#include "gov_cca_ports_GoPort.hxx"
// DO-NOT-DELETE splicer.end(drivers.CXXDriver._includes)
...
Note that in naming files, Babel translates periods
(“.”) in the SIDL to underscores
(“_”).
Now, although the component is not complete, it is a good idea to check that it compiles correctly with the code you've added so far.
First, change directories to and
run $STUDENT_SRC/componentsmake drivers. This will install
Makefile and
MakeIncl.user files in .
$STUDENT_SRC/components/drivers/cxx
Then, change directories to
and run $STUDENT_SRC/components/drivers/cxxmake. If you get any compiler
errors, you should fix them before going on.
Once again, edit
and add the implementation of the $STUDENT_SRC/components/drivers/cxx/drivers_CXXDriver_Impl.cxx
go
method:
... /** * Method: go[] */ int32_t drivers::CXXDriver_impl::go () throw () { // DO-NOT-DELETE splicer.begin(drivers.CXXDriver.go) // insert implementation heredouble value;![]()
int count = 100000; double lowerBound = 0.0, upperBound = 1.0; ::integrator::IntegratorPort integrator;![]()
// get the port ... gov::cca::Port port = frameworkServices.getPort("IntegratorPort"); integrator = babel_cast< ::integrator::IntegratorPort >(port);![]()
if(integrator._is_nil()) {![]()
fprintf(stdout, "drivers.CXXDriver not connected\n"); frameworkServices.releasePort("IntegratorPort"); return -1; } // operate on the port value = integrator.integrate (lowerBound, upperBound, count);![]()
fprintf(stdout,"Value = %lf\n", value); fflush(stdout); // release the port. frameworkServices.releasePort("IntegratorPort");![]()
return 0;// DO-NOT-DELETE splicer.end(drivers.CXXDriver.go) } ...
Congratulations, you have completed the implementation of the
CXXDriver! To check your work, run
make in .
If you get any compiler errors, you should fix them before going
on.
$STUDENT_SRC/components/drivers/cxx
At this point, it is a good idea to go up to and run
$STUDENT_SRCmake to insure that anything else which
might depend on the existence of the new
drivers.CXXDriver component gets built too.
The next step is to test your new driver component, in Section 3.5, “Using Your New Component”.