Edit the evaluate and init methods
in the implementation file (also known as "the impl") that bocca has generated for you (by invoking Babel).
Use the bocca edit -i to go directly to each method.
$bocca edit -i Function evaluate/** * Method: evaluate[] */ double myProject::Function_impl::evaluate_impl ( /* in */double x ) { // DO-NOT-DELETE splicer.begin(myProject.Function.evaluate) // Insert-Code-Here {myProject.Function.evaluate} (evaluate method) // DO-DELETE-WHEN-IMPLEMENTING exception.begin() /* * This method has not been implemented */ ::sidl::NotImplementedException ex = ::sidl::NotImplementedException::_create(); ex.setNote("This method has not been implemented"); ex.add(__FILE__, __LINE__, "evaluate"); throw ex; // DO-DELETE-WHEN-IMPLEMENTING exception.end() // DO-NOT-DELETE splicer.end(myProject.Function.evaluate) }
As the comment suggests, this method is "not implemented", but some code
has been inserted by Babel to make sure an exception is thrown to
inform the user if this method is called by mistake. Remove this boilerplate
exception code
and substitute an implementation for the
PiFunction (i.e., the integral from 0 to 1 of
4/(1 + x2) is π).
/**
* Method: evaluate[]
*/
double
myProject::Function_impl::evaluate_impl (
/* in */double x )
{
// DO-NOT-DELETE splicer.begin(myProject.Function.evaluate)
return 4.0 / (1.0 + x * x);
// DO-NOT-DELETE splicer.end(myProject.Function.evaluate)
}
Now in the same file just above the evaluate method,
find the second method for the FunctionPort
init method:
/**
* Method: init[]
*/
void
myProject::Function_impl::init_impl (
/* in array<double> */::sidl::array<double> params )
{
// DO-NOT-DELETE splicer.begin(myProject.Function.init)
// Do nothing.
// DO-NOT-DELETE splicer.end(myProject.Function.init)
}
We don't have any initialization in this simple example, so we just eliminate the code that throws the exception when the method is executed.
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited.
Trying to edit file /data/user1/myProject/components/myProject.Function/myProject_Function_Impl.cxx
$
Similarly change integrate in Integrator with:
$bocca edit -i Integrator integrate/** * Method: integrate[] */ double myProject::Integrator_impl::integrate_impl ( /* in */double lowBound, /* in */double upBound, /* in */int32_t count ) { // DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate) // Insert-Code-Here {myProject.Integrator.integrate} (integrate method) // DO-DELETE-WHEN-IMPLEMENTING exception.begin() /* * This method has not been implemented */ ::sidl::NotImplementedException ex = ::sidl::NotImplementedException::_create(); ex.setNote("This method has not been implemented"); ex.add(__FILE__, __LINE__, "integrate"); throw ex; // DO-DELETE-WHEN-IMPLEMENTING exception.end() // DO-NOT-DELETE splicer.end(myProject.Integrator.integrate) }
Remove this boilerplate exception code and insert an implementation of the
Trapezoid rule for integration that uses the FunctionPort:
/**
* Method: integrate[]
*/
double
myProject::Integrator_impl::integrate_impl (
/* in */double lowBound,
/* in */double upBound,
/* in */int32_t count )
{
// DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate)
myProject::FunctionPort integrateThis;
gov::cca::Port generalPort;
try {
generalPort = d_services.getPort("integrateThis");
} catch ( ::gov::cca::CCAException ex) {
// we cannot go on. add to the error report.
ex.add( __FILE__, __LINE__,
"integrateThis port not available in Integrator.integrate");
throw;
}
integrateThis = ::babel_cast< myProject::FunctionPort >(generalPort);
if (integrateThis._is_nil()){
// we cannot go on. toss an exception after cleaning up.
try {
d_services.releasePort("integrateThis");
} catch (...) {
// suppress framework complaints; we're already handling an exception.
}
::sidl::SIDLException ex = ::sidl::SIDLException::_create();
ex.setNote("Error: integrateThis port is nil. Weird.");
ex.add(__FILE__, __LINE__, "integrators::Trapezoid_impl::integrate_impl");
throw ex;
}
double h = (upBound - lowBound) / count;
double retval = 0.0;
double sum = 0.0;
for (int i = 1; i <= count; i++){
sum += integrateThis.evaluate(lowBound + (i - 1) * h) +
integrateThis.evaluate(lowBound + i * h);
}
retval = h/2.0 * sum;
d_services.releasePort("integrateThis");
return retval;
// DO-NOT-DELETE splicer.end(myProject.Integrator.integrate)
}
We see the usual output when no other sources depend on the one just edited.
Trying to edit file /data/user1/myProject/components/myProject.Integrator/myProject_Integrator_Impl.cxx
$
Finally for the Driver component
we have to implement the GoPort details to get things going.
Bocca will take you to the generated method, which looks like:
$bocca edit -i Driver go/** * * Execute some encapsulated functionality on the component. * Return 0 if ok, -1 if internal error but component may be * used further, and -2 if error so severe that component cannot * be further used safely. */ int32_t myProject::Driver_impl::go_impl () { // DO-NOT-DELETE splicer.begin(myProject.Driver.go) // User editable portion is in the middle at the next Insert-UserCode-Here line. // Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoProlog) int bocca_status = 0; // The user's code should set bocca_status 0 if computation proceeded ok. // The user's code should set bocca_status -1 if computation failed but might // succeed on another call to go(), e.g. when a required port is not yet connected. // The user's code should set bocca_status -2 if the computation failed and can // never succeed in a future call. // The user's code should NOT use return in this function; // Exceptions that are not caught in user code will be converted to status -2. gov::cca::Port port; myProject::IntegratorPort integrate; // nil if not fetched and cast successfully. bool integrate_fetched = false; // True when releasePort is needed (even if cast fails). // Use a myProject.IntegratorPort port with port name integrate try{ port = this->d_services.getPort("integrate"); } catch ( ::gov::cca::CCAException ex ) { // we will continue with port nil (never successfully assigned) and set a flag. #ifdef _BOCCA_STDERR std::cerr << "myProject.Driver: Error calling getPort(\"integrate\") at " << __FILE__ << ":" << __LINE__ -5 << ": " << ex.getNote() << std::endl; #endif // _BOCCA_STDERR } if ( port._not_nil() ) { integrate_fetched = true; // even if the next cast fails, must release. integrate = ::babel_cast< myProject::IntegratorPort >(port); if (integrate._is_nil()) { #ifdef _BOCCA_STDERR std::cerr << "myProject.Driver: Error casting gov::cca::Port integrate to type myProject::IntegratorPort" << std::endl; #endif //_BOCCA_STDERR goto BOCCAEXIT; // we cannot correctly continue. clean up and leave. } } // Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoProlog) // When this try/catch block is rewritten by the user, we will not change it. try { // All port instances should be rechecked for ._not_nil before calling in user code. // Not all ports need be connected in arbitrary use. // The uses ports appear as local variables here named exactly as on the // bocca commandline. // Insert-UserCode-Here {myProject.Driver.go} // REMOVE ME BLOCK.begin(myProject.Driver.go) #ifdef _BOCCA_STDERR std::cerr << "USER FORGOT TO FILL IN THEIR GO FUNCTION HERE." << std::endl; #endif // REMOVE ME BLOCK.end(myProject.Driver.go) } // If unknown exceptions in the user code are tolerable and restart is ok, return -1 instead. // -2 means the component is so confused that it and probably the application should be // destroyed. catch (sidl::BaseException ex) { bocca_status = -2; std::string enote = ex.getNote(); #ifdef _BOCCA_STDERR std::cerr << "Exception in user go code: " << enote << std::endl; std::cerr << "Returning -2 from go()" << std::endl;; #endif } catch (std::exception ex) { bocca_status = -2; #ifdef _BOCCA_STDERR std::cerr << "C++ exception in user go code: " << ex.what() << std::endl; std::cerr << "Returning -2 from go()" << std::endl; #endif } catch (...) { bocca_status = -2; #ifdef _BOCCA_STDERR std::cerr << "Odd exception in user go code " << std::endl; std::cerr << "Returning -2 from go()" << std::endl; #endif } BOCCAEXIT:; // target point for error and regular cleanup. do not delete. // Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoEpilog) // release integrate if (integrate_fetched) { integrate_fetched = false; try{ this->d_services.releasePort("integrate"); } catch ( ::gov::cca::CCAException ex ) { #ifdef _BOCCA_STDERR std::cerr << "myProject.Driver: Error calling releasePort(\"integrate\") at " << __FILE__ << ":" << __LINE__ -4 << ": " << ex.getNote() << std::endl; #endif // _BOCCA_STDERR } // c++ port reference will be dropped when function exits, but we must tell framework. } return bocca_status; // Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoEpilog) // DO-NOT-DELETE splicer.end(myProject.Driver.go) }
For complex components with many ports (or even one port in languages which are not object-oriented), the default go implementation is very handy. Because we have only one port to use in this C++ example, we will delete the bocca default go implementation entirely. Bocca will not attempt to regenerate it once deleted.
Delete everything between the DO-NOT-DELETE
splicer directives and insert an implementation of the
GoPort method
go as shown. The go
function will be called by the framework when the component's
run button (the name of this particular GoPort instance)
is pushed in the GUI. We will implement that method to get a
reference to the IntegratorPort that the Driver has
been connected to and use it to compute the integral:
/**
*
* Execute some encapsulated functionality on the component.
* Return 0 if ok, -1 if internal error but component may be
* used further, and -2 if error so severe that component cannot
* be further used safely.
*/
int32_t
myProject::Driver_impl::go_impl ()
{
// DO-NOT-DELETE splicer.begin(myProject.Driver.go)
double value;
int count = 100000;
double lowerBound = 0.0, upperBound = 1.0;
::myProject::IntegratorPort integrator;
// get the port ...
gov::cca::Port port = d_services.getPort("integrate");
integrator = babel_cast< ::myProject::IntegratorPort >(port);
if(integrator._is_nil()) {
std::cerr << "Weird error in casting integrate port." << std::endl;
d_services.releasePort("integrate");
return -2;
}
// operate on the port
value = integrator.integrate(lowerBound, upperBound, count);
std::cout << "Value = " << value << std::endl;
// release the port.
d_services.releasePort("integrate");
return 0;
// DO-NOT-DELETE splicer.end(myProject.Driver.go)
}
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited.
Trying to edit file /data/user1/myProject/components/myProject.Driver/myProject_Driver_Impl.cxx
$
Now remake your project tree to finish the components:
$make# ======================================================================= # No SIDL files in external/sidl, skipping build for external # ======================================================================= # ======================================================================= # Building in ports/, languages: cxx # ======================================================================= ## Building ports... # ======================================================================= # Building in components/clients/, languages: cxx # ======================================================================= ## Building clients... # ======================================================================= # Building in components/, languages: cxx # ======================================================================= [s] Building component myProject.Driver: [s] creating component library: libmyProject.Driver.la ... [s] finished libtooling: components/myProject.Driver/libmyProject.Driver.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.Function: [s] creating component library: libmyProject.Function.la ... [s] finished libtooling: components/myProject.Function/libmyProject.Function.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.Integrator: [s] creating component library: libmyProject.Integrator.la ... [s] finished libtooling: components/myProject.Integrator/libmyProject.Integrator.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.emptyComponent: doing nothing -- library is up-to-date. Build summary: SUCCESS building myProject.Driver SUCCESS building myProject.Function SUCCESS building myProject.Integrator ### To test instantiation of successfully built components, run 'make check' ### ################ Finished building everything ################# ####### You can run some simple tests with 'make check' #######$
It is good practice to do a make check at this point:
$make checkmake --no-print-directory --no-builtin-rules -C components check ### Test library load and instantiation for the following languages: cxx Running instantiation tests only Test script: /data/user1/myProject/components/tests/instantiation.gen.rc SUCCESS: ==> Instantiation tests passed for all built components (see /data/user1/myProject/components/tests/instantiation.gen.rc.log). make --no-print-directory --no-builtin-rules check-user$
You should now be able to instantiate these components, assemble them into an application, and run the application, following the same procedures as in Chapter 2, Assembling and Running a CCA Application, and get a result that's reasonably close to π.
You can now implement the evaluate method generated
from the SIDL definition of the FunctionPort method
evaluate. The bocca edit command
will take you directly to the method in the source file, skipping over the
many details of generating portable object-oriented F90 code.
$bocca edit -i Function evaluate! ! Method: evaluate[] ! recursive subroutine myProject_Function_evaluate_mi(self, x, retval, & exception) use sidl use sidl_NotImplementedException use sidl_BaseInterface use sidl_RuntimeException use myProject_Function use myProject_Function_impl ! DO-NOT-DELETE splicer.begin(myProject.Function.evaluate.use) ! Insert-Code-Here {myProject.Function.evaluate.use} (use statements) ! DO-NOT-DELETE splicer.end(myProject.Function.evaluate.use) implicit none type(myProject_Function_t) :: self ! in real (kind=sidl_double) :: x ! in real (kind=sidl_double) :: retval ! out type(sidl_BaseInterface_t) :: exception ! out ! DO-NOT-DELETE splicer.begin(myProject.Function.evaluate) ! Insert-Code-Here {myProject.Function.evaluate} (evaluate method) ! DO-DELETE-WHEN-IMPLEMENTING exception.begin() ! ! This method has not been implemented ! type(sidl_BaseInterface_t) :: throwaway type(sidl_NotImplementedException_t) :: notImpl call new(notImpl, exception) call setNote(notImpl, 'Not Implemented', exception) call cast(notImpl, exception,throwaway) call deleteRef(notImpl,throwaway) return ! DO-DELETE-WHEN-IMPLEMENTING exception.end() ! DO-NOT-DELETE splicer.end(myProject.Function.evaluate) end subroutine myProject_Function_evaluate_mi
As the comment suggests, this method is "not implemented", but some code
has been inserted by Babel to make sure an exception is thrown to
inform the user if this is called by mistake. Remove this boilerplate
exception code and substitute an implementation for the
PiFunction (i.e., the integral from 0 to 1 of
4/(1 + x2) is π).
!
! Method: evaluate[]
!
recursive subroutine myProject_Function_evaluate_mi(self, x, retval, &
exception)
use sidl
use sidl_NotImplementedException
use sidl_BaseInterface
use sidl_RuntimeException
use myProject_Function
use myProject_Function_impl
! DO-NOT-DELETE splicer.begin(myProject.Function.evaluate.use)
! Insert-Code-Here {myProject.Function.evaluate.use} (use statements)
! DO-NOT-DELETE splicer.end(myProject.Function.evaluate.use)
implicit none
type(myProject_Function_t) :: self ! in
real (kind=sidl_double) :: x ! in
real (kind=sidl_double) :: retval ! out
type(sidl_BaseInterface_t) :: exception ! out
! DO-NOT-DELETE splicer.begin(myProject.Function.evaluate)
! 4/(1+x^2)
retval = 4.0 / (1.0 + x*x)
! DO-NOT-DELETE splicer.end(myProject.Function.evaluate)
end subroutine myProject_Function_evaluate_mi
Now in the same file find the FunctionPort interface init
method:
recursive subroutine myProject_Function_init_mi(self, params, exception)
use sidl
use sidl_NotImplementedException
use sidl_BaseInterface
use sidl_RuntimeException
use myProject_Function
use sidl_double_array
use myProject_Function_impl
! DO-NOT-DELETE splicer.begin(myProject.Function.init.use)
! Insert-Code-Here {myProject.Function.init.use} (use statements)
! DO-NOT-DELETE splicer.end(myProject.Function.init.use)
implicit none
type(myProject_Function_t) :: self ! in
type(sidl_double_1d) :: params ! in
type(sidl_BaseInterface_t) :: exception ! out
! DO-NOT-DELETE splicer.begin(myProject.Function.init)
! Do nothing.
! DO-NOT-DELETE splicer.end(myProject.Function.init)
end subroutine myProject_Function_init_mi
We don't have any initialization in this simple example, so we just eliminate the code that throws the exception when the method is executed.
After quitting the editor the state of the build tree is updated. Usually there are no source code dependencies on the implementation file, so bocca does nothing more than name the file that changed.
Trying to edit file /data/user1/myProject/components/myProject.Function/myProject_Function_Impl.F90
$
Next implement Integrator's integrate method with bocca edit:
$bocca edit -i Integrator integrate! ! Method: integrate[] ! recursive subroutine Integrat_integrate27jlju5gbk_mi(self, lowBound, upBound, & count, retval, exception) use sidl use sidl_NotImplementedException use sidl_BaseInterface use sidl_RuntimeException use myProject_Integrator use myProject_Integrator_impl ! DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate.use) ! Insert-Code-Here {myProject.Integrator.integrate.use} (use statements) ! DO-NOT-DELETE splicer.end(myProject.Integrator.integrate.use) implicit none type(myProject_Integrator_t) :: self ! in real (kind=sidl_double) :: lowBound ! in real (kind=sidl_double) :: upBound ! in integer (kind=sidl_int) :: count ! in real (kind=sidl_double) :: retval ! out type(sidl_BaseInterface_t) :: exception ! out ! DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate) ! Insert-Code-Here {myProject.Integrator.integrate} (integrate method) ! DO-DELETE-WHEN-IMPLEMENTING exception.begin() ! ! This method has not been implemented ! type(sidl_BaseInterface_t) :: throwaway type(sidl_NotImplementedException_t) :: notImpl call new(notImpl, exception) call setNote(notImpl, 'Not Implemented', exception) call cast(notImpl, exception,throwaway) call deleteRef(notImpl,throwaway) return ! DO-DELETE-WHEN-IMPLEMENTING exception.end() ! DO-NOT-DELETE splicer.end(myProject.Integrator.integrate) end subroutine Integrat_integrate27jlju5gbk_mi
Again remove this boilerplate exception code and insert an implementation of the
Trapezoid rule for integration that uses the FunctionPort:
!
! Method: integrate[]
!
recursive subroutine Integrat_integrate27jlju5gbk_mi(self, lowBound, upBound, &
count, retval, exception)
use sidl
use sidl_NotImplementedException
use sidl_BaseInterface
use sidl_RuntimeException
use myProject_Integrator
use myProject_Integrator_impl
! DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate.use)
! the port types we need go here.
use gov_cca_Port
use myProject_FunctionPort
! DO-NOT-DELETE splicer.end(myProject.Integrator.integrate.use)
implicit none
type(myProject_Integrator_t) :: self ! in
real (kind=sidl_double) :: lowBound ! in
real (kind=sidl_double) :: upBound ! in
integer (kind=sidl_int) :: count ! in
real (kind=sidl_double) :: retval ! out
type(sidl_BaseInterface_t) :: exception ! out
! DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate)
! local declarations. We follow the pattern generated for us in Driver.go()
type(gov_cca_Port_t) :: port
type(gov_cca_Services_t) :: services
type(SIDL_BaseInterface_t) :: throwaway
type(SIDL_BaseInterface_t) :: dumex
type(myProject_Integrator_wrap) :: dp
logical dr_port ! if dr_X true, the deleteRef(X) is needed before return.
type(myProject_FunctionPort_t) :: integrateThis__p
! integrateThis__p is non-null if specific uses port obtained.
logical integrateThis_fetched
! integrateThis_fetched true if releaseport is needed for this port.
! a small message catalog for exception reporting
character (LEN=*) errMsg00
character (LEN=*) errMsg0
character (LEN=*) errMsg1
character (LEN=*) errMsg2
character (LEN=*) errMsg3
character (LEN=*) errMsg4
parameter(errMsg00= &
'NULL d_services pointer in myProject.Integrator.integrate()')
parameter(errMsg0= &
'myProject.Integrator: Error go() getPort(integrateThis) failed.')
parameter(errMsg1= &
'myProject.Integrator: Error casting integrateThis to FunctionPort')
parameter(errMsg2= &
'myProject.Integrator: Error in deleteRef(port) while getting integrateThis')
parameter(errMsg3= &
'myProject.Integrator: Error calling releasePort(integrateThis).')
parameter(errMsg4= &
'myProject.Integrator: Error in deleteRef for port integrateThis.')
! numerical method variable, other than the call arguments:
real (kind=sidl_double) :: h, fvalueleft, fvalueright, sum, left, right
integer i
BOCCA_EXTERNAL
! not crashing if something fails .eq. good bookkeeping and exception handling.
! start with initialization
call set_null( integrateThis__p)
integrateThis_fetched = .false.
call set_null(services)
call set_null(port)
call set_null(throwaway)
call set_null(dumex)
dr_port = .false.
call myProject_Integrator__get_data_m(self,dp);
services = dp%d_private_data%d_services
retval = -4.0
if (is_null(services) ) then
call BOCCA_SIDL_THROW_F90(exception, errMsg00)
endif
! Use a myProject.FunctionPort port with port name integrateThis
call getPort(services,"integrateThis", port, exception)
BOCCA_SIDL_CHECK_F90(exception, errMsg0)
integrateThis_fetched = .true.
! even if the next cast fails, must releasePort per integrateThis_fetched.
call cast(port, integrateThis__p, exception)
BOCCA_SIDL_CHECK_F90(exception, errMsg1)
! done with the generic port pointer. drop it.
call deleteRef(port, exception)
call set_null(port)
BOCCA_SIDL_CHECK_F90(exception, errMsg2)
!! here's the numerical work
! the trapezoidal rule
h = (upBound - lowBound) / count
sum = 0.0
fvalueleft = 0.0
fvalueright = 0.0
do i = 1,count
left = lowBound + (i - 1) * h
call evaluate(integrateThis__p, left, fvalueleft, exception)
BOCCA_SIDL_CHECK_F90(exception, 'error calculating fvalueleft')
right = lowBound + i * h
call evaluate(integrateThis__p, right, fvalueright, exception)
BOCCA_SIDL_CHECK_F90(exception, 'error calculating fvalueright')
sum = sum + fvalueleft + fvalueright
enddo
retval = h/2.0 * sum;
!! the numerical work is done.
BOCCAEXIT continue ! target point for normal and error cleanup.
if (not_null(port)) then
call deleteRef(port,throwaway)
call checkException(self, throwaway, 'cleanup port error', .false., dumex)
call set_null(port)
endif
! release integrateThis
if (integrateThis_fetched) then
integrateThis_fetched = .false.
call releasePort(services, 'integrateThis', throwaway)
call checkException(self, throwaway, errMsg3, .false., dumex)
if ( not_null(integrateThis__p) ) then
call deleteRef(integrateThis__p, throwaway)
call checkException(self, throwaway, errMsg4, .false., dumex)
call set_null(integrateThis__p)
endif
endif
! DO-NOT-DELETE splicer.end(myProject.Integrator.integrate)
end subroutine Integrat_integrate27jlju5gbk_mi
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited
Trying to edit file /data/user1/myProject/components/myProject.Integrator/myProject_Integrator_Impl.F90
$
We must now implement the GoPort to get things going.
Finally implement the Driver component's go function using
bocca edit. The generated method with the object management logic looks like:
$bocca edit -i Driver go! ! Method: go[] ! ! Execute some encapsulated functionality on the component. ! Return 0 if ok, -1 if internal error but component may be ! used further, and -2 if error so severe that component cannot ! be further used safely. ! recursive subroutine myProject_Driver_go_mi(self, retval, exception) use sidl use sidl_NotImplementedException use sidl_BaseInterface use sidl_RuntimeException use myProject_Driver use myProject_Driver_impl ! DO-NOT-DELETE splicer.begin(myProject.Driver.go.use) /* Bocca generated code. bocca.protected.begin(myProject.Driver.go.use) */ use gov_cca_Port use myProject_IntegratorPort /* Bocca generated code. bocca.protected.end(myProject.Driver.go.use) */ ! DO-NOT-DELETE splicer.end(myProject.Driver.go.use) implicit none type(myProject_Driver_t) :: self ! in integer (kind=sidl_int) :: retval ! out type(sidl_BaseInterface_t) :: exception ! out ! DO-NOT-DELETE splicer.begin(myProject.Driver.go) ! Insert-User-Declarations-Here ! Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoProlog) integer bocca_status ! The user's code should set bocca_status 0 if computation proceeded ok. ! The user's code should set bocca_status -1 if computation failed but might ! succeed on another call to go(), e.g. when a required port is not yet connected. ! The user's code should set bocca_status -2 if the computation failed and can ! never succeed in a future call. ! The user's code should NOT use return in this function; ! Exceptions that are not caught in user code will be converted to status -2. ! type(gov_cca_Port_t) :: port type(gov_cca_Services_t) :: services type(SIDL_BaseInterface_t) :: throwaway type(SIDL_BaseInterface_t) :: dumex type(myProject_Driver_wrap) :: dp logical dr_port ! if dr_X true, the deleteRef(X) is needed before return. type(myProject_IntegratorPort_t) :: integrate__p ! non-null if specific uses port obtained. logical integrate_fetched ! true if releaseport is needed for this port. character (LEN=*) errMsg0_integrate character (LEN=*) errMsg1_integrate character (LEN=*) errMsg2_integrate character (LEN=*) errMsg3_integrate character (LEN=*) errMsg4_integrate parameter(errMsg0_integrate= & 'myProject.Driver: Error go() getPort(integrate) failed.') parameter(errMsg1_integrate= & 'myProject.Driver: Error casting gov.cca.Port integrate to type myProject.IntegratorPort') parameter(errMsg2_integrate= & 'myProject.Driver: Error in deleteRef(port) while getting integrate') parameter(errMsg3_integrate= & 'myProject.Driver: Error calling releasePort(integrate). Continuing.') parameter(errMsg4_integrate = & 'myProject.Driver: Error in deleteRef for port integrate. Continuing.') BOCCA_EXTERNAL ! not crashing if something fails requires good bookkeeping and exception handling. call set_null(services) call set_null(port) call set_null(throwaway) call set_null(dumex) dr_port = .false. bocca_status = 0 call myProject_Driver__get_data_m(self,dp); services = dp%d_private_data%d_services if (is_null(services) ) then call BOCCA_SIDL_THROW_F90(exception, 'NULL d_services pointer in myProject.Driver.go()') endif /* Use a myProject.IntegratorPort port with port name integrate */ call getPort(services,"integrate", port, throwaway) if ( not_null(throwaway) ) then call set_null(port) call checkException(self, throwaway, errMsg0_integrate, .false., dumex) ! we will continue with port null (never successfully assigned) and set a flag. endif call set_null( integrate__p) integrate_fetched = .false. if ( not_null(port)) then integrate_fetched = .true. ! even if the next cast fails, must releasePort. call cast(port, integrate__p, exception) BOCCA_SIDL_CHECK_F90(exception, errMsg1_integrate) call deleteRef(port, exception) call set_null(port) BOCCA_SIDL_CHECK_F90(exception, errMsg2_integrate) endif /* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoProlog) */ ! When this block is rewritten by the user, we will not change it. ! All port instances should be rechecked for NULL before calling in user code. ! Not all ports need be connected in arbitrary use. ! The port instance names used in registerUsesPort appear as local variable ! names here with the suffix __p added. ! BEGIN REMOVE ME BLOCK #ifdef _BOCCA_STDERR write(*,*) 'USER FORGOT TO FILL IN THEIR FUNCTION myProject.Driver.go.' #endif ! END REMOVE ME BLOCK ! If unknown exceptions in the user code are tolerable and restart is ok, set bocca_status -1 instead. ! -2 means the component is so confused that it and probably the application should be ! destroyed. ! BOCCAEXIT continue ! target point for normal and error cleanup. do not delete. /* Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoEpilog) */ if (not_null(port)) then call deleteRef(port,throwaway) call checkException(self, throwaway, 'cleanup port error', .false., dumex) call set_null(port) endif ! release integrate if (integrate_fetched) then integrate_fetched = .false. call releasePort(services, 'integrate', throwaway) call checkException(self, throwaway, errMsg3_integrate, .false., dumex) if ( not_null(integrate__p) ) then call deleteRef(integrate__p, throwaway) call checkException(self, throwaway, errMsg4_integrate, .false., dumex) call set_null(integrate__p) endif endif /* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoEpilog) */ ! Insert-User-Exception-Cleanup-Here retval = bocca_status ! DO-NOT-DELETE splicer.end(myProject.Driver.go) end subroutine myProject_Driver_go_mi
Find the REMOVE block within the go method implementation,
delete it, and insert the numerical logic needed to use the integrator.IntegratorPort port.
Any required local variables should be inserted just before the boccaGoProlog
protected block.
As indicated in the code comments, each uses port appears
as a local variable with the name of the port followed by __p.
The go subroutine will be called by the
framework when the component's run button (the name of this
particular GoPort instance) is pushed in the GUI. Bocca
generates the default fetching of the IntegratorPort that the
Driver is connected to. We just have to use it to compute the
integral and return the proper value for bocca_status.
!
! Method: go[]
!
! Execute some encapsulated functionality on the component.
! Return 0 if ok, -1 if internal error but component may be
! used further, and -2 if error so severe that component cannot
! be further used safely.
!
recursive subroutine myProject_Driver_go_mi(self, retval, exception)
use sidl
use sidl_NotImplementedException
use sidl_BaseInterface
use sidl_RuntimeException
use myProject_Driver
use myProject_Driver_impl
! DO-NOT-DELETE splicer.begin(myProject.Driver.go.use)
/* Bocca generated code. bocca.protected.begin(myProject.Driver.go.use) */
use gov_cca_Port
use myProject_IntegratorPort
/* Bocca generated code. bocca.protected.end(myProject.Driver.go.use) */
! DO-NOT-DELETE splicer.end(myProject.Driver.go.use)
implicit none
type(myProject_Driver_t) :: self ! in
integer (kind=sidl_int) :: retval ! out
type(sidl_BaseInterface_t) :: exception ! out
! DO-NOT-DELETE splicer.begin(myProject.Driver.go)
! local variables for integration
real (kind=sidl_double) :: lowBound
real (kind=sidl_double) :: upBound
integer (kind=sidl_int) :: count
real (kind=sidl_double) :: value
! Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoProlog)
integer bocca_status
! The user's code should set bocca_status 0 if computation proceeded ok.
! The user's code should set bocca_status -1 if computation failed but might
! succeed on another call to go(), e.g. when a required port is not yet connected.
! The user's code should set bocca_status -2 if the computation failed and can
! never succeed in a future call.
! The user's code should NOT use return in this function;
! Exceptions that are not caught in user code will be converted to status -2.
!
type(gov_cca_Port_t) :: port
type(gov_cca_Services_t) :: services
type(SIDL_BaseInterface_t) :: throwaway
type(SIDL_BaseInterface_t) :: dumex
type(myProject_Driver_wrap) :: dp
logical dr_port ! if dr_X true, the deleteRef(X) is needed before return.
type(myProject_IntegratorPort_t) :: integrate__p ! non-null if specific uses port obtained.
logical integrate_fetched ! true if releaseport is needed for this port.
character (LEN=*) errMsg0_integrate
character (LEN=*) errMsg1_integrate
character (LEN=*) errMsg2_integrate
character (LEN=*) errMsg3_integrate
character (LEN=*) errMsg4_integrate
parameter(errMsg0_integrate= &
'myProject.Driver: Error go() getPort(integrate) failed.')
parameter(errMsg1_integrate= &
'myProject.Driver: Error casting gov.cca.Port integrate to type myProject.IntegratorPort')
parameter(errMsg2_integrate= &
'myProject.Driver: Error in deleteRef(port) while getting integrate')
parameter(errMsg3_integrate= &
'myProject.Driver: Error calling releasePort(integrate). Continuing.')
parameter(errMsg4_integrate = &
'myProject.Driver: Error in deleteRef for port integrate. Continuing.')
BOCCA_EXTERNAL
! not crashing if something fails requires good bookkeeping and exception handling.
call set_null(services)
call set_null(port)
call set_null(throwaway)
call set_null(dumex)
dr_port = .false.
bocca_status = 0
call myProject_Driver__get_data_m(self,dp);
services = dp%d_private_data%d_services
if (is_null(services) ) then
call BOCCA_SIDL_THROW_F90(exception, 'NULL d_services pointer in myProject.Driver.go()')
endif
/* Use a myProject.IntegratorPort port with port name integrate */
call getPort(services,"integrate", port, throwaway)
if ( not_null(throwaway) ) then
call set_null(port)
call checkException(self, throwaway, errMsg0_integrate, .false., dumex)
! we will continue with port null (never successfully assigned) and set a flag.
endif
call set_null( integrate__p)
integrate_fetched = .false.
if ( not_null(port)) then
integrate_fetched = .true. ! even if the next cast fails, must releasePort.
call cast(port, integrate__p, exception)
BOCCA_SIDL_CHECK_F90(exception, errMsg1_integrate)
call deleteRef(port, exception)
call set_null(port)
BOCCA_SIDL_CHECK_F90(exception, errMsg2_integrate)
endif
/* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoProlog) */
! Initialize local variables
count = 100000
lowBound = 0.0
upBound = 1.0
if (not_null(integrate__p)) then
value = -1.0 ! nonsense number to confirm it is set
! operate on the port. if successful, set the status to 0 for ok.
bocca_status = -2
call integrate(integrate__p, lowBound, upBound, count, value, exception)
! jump to BOCCAEXIT if an error.
BOCCA_SIDL_CHECK_F90(exception,'Driver:go: problem calling integrate')
write(*,*) 'Value = ', value
bocca_status = 0
else
bocca_status = -1 ; ! integratorPort is not connected.
write(*,*) 'Driver: integrate port not connected. connect and try again'
endif
BOCCAEXIT continue ! target point for normal and error cleanup. do not delete.
/* Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoEpilog) */
if (not_null(port)) then
call deleteRef(port,throwaway)
call checkException(self, throwaway, 'cleanup port error', .false., dumex)
call set_null(port)
endif
! release integrate
if (integrate_fetched) then
integrate_fetched = .false.
call releasePort(services, 'integrate', throwaway)
call checkException(self, throwaway, errMsg3_integrate, .false., dumex)
if ( not_null(integrate__p) ) then
call deleteRef(integrate__p, throwaway)
call checkException(self, throwaway, errMsg4_integrate, .false., dumex)
call set_null(integrate__p)
endif
endif
/* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoEpilog) */
retval = bocca_status
! DO-NOT-DELETE splicer.end(myProject.Driver.go)
end subroutine myProject_Driver_go_mi
After quitting the editor the state of the build tree is updated if needed. Again in this case nothing else needs updating.
Trying to edit file /data/user1/myProject/components/myProject.Driver/myProject_Driver_Impl.F90
$
Now remake your project tree to finish the components:
$make# ======================================================================= # No SIDL files in external/sidl, skipping build for external # ======================================================================= # ======================================================================= # Building in ports/, languages: f90 # ======================================================================= ## Building ports... # ======================================================================= # Building in components/clients/, languages: f90 # ======================================================================= ## Building clients... # ======================================================================= # Building in components/, languages: f90 # ======================================================================= [s] Building component myProject.Driver: [s] creating component library: libmyProject.Driver.la ... [s] finished libtooling: components/myProject.Driver/libmyProject.Driver.la ... [s] creating component library: libmyProject.Driver.la ... [s] finished libtooling: components/myProject.Driver/libmyProject.Driver.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.Function: [s] creating component library: libmyProject.Function.la ... [s] finished libtooling: components/myProject.Function/libmyProject.Function.la ... [s] creating component library: libmyProject.Function.la ... [s] finished libtooling: components/myProject.Function/libmyProject.Function.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.Integrator: [s] creating component library: libmyProject.Integrator.la ... [s] finished libtooling: components/myProject.Integrator/libmyProject.Integrator.la ... [s] creating component library: libmyProject.Integrator.la ... [s] finished libtooling: components/myProject.Integrator/libmyProject.Integrator.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.emptyComponent: doing nothing -- library is up-to-date. Build summary: SUCCESS building myProject.Driver SUCCESS building myProject.Function SUCCESS building myProject.Integrator ### To test instantiation of successfully built components, run 'make check' ### ################ Finished building everything ################# ####### You can run some simple tests with 'make check' #######$
You should now be able to instantiate these components, assemble them into an application, and run the application, following the same procedures as in Chapter 2, Assembling and Running a CCA Application, and get a result that's reasonably close to π.
Edit the evaluate and init methods
in the implementation file (also known as "the impl") that bocca has generated for you (by invoking Babel).
Use the bocca edit -i to go directly to each method.
$bocca edit -i Function evaluate/* * Method: evaluate[] */ #undef __FUNC__ #define __FUNC__ "impl_myProject_Function_evaluate" #ifdef __cplusplus extern "C" #endif double impl_myProject_Function_evaluate( /* in */ myProject_Function self, /* in */ double x, /* out */ sidl_BaseInterface *_ex) { *_ex = 0; { /* DO-NOT-DELETE splicer.begin(myProject.Function.evaluate) */ /* Insert-Code-Here {myProject.Function.evaluate} (evaluate method) */ /* DO-DELETE-WHEN-IMPLEMENTING exception.begin() */ /* * This method has not been implemented. */ SIDL_THROW(*_ex, sidl_NotImplementedException, "This method has not been implemented"); EXIT:; /* DO-DELETE-WHEN-IMPLEMENTING exception.end() */ /* DO-NOT-DELETE splicer.end(myProject.Function.evaluate) */ } }
As the comment suggests this method is "not implemented", but some code
has been inserted by Babel to make sure an exception is thrown to
inform the user if this method is called by mistake. Remove this boilerplate
exception code
and substitute an implementation for the
PiFunction (i.e., the integral from 0 to 1 of
4/(1 + x2) is π).
/*
* Method: evaluate[]
*/
#undef __FUNC__
#define __FUNC__ "impl_myProject_Function_evaluate"
#ifdef __cplusplus
extern "C"
#endif
double
impl_myProject_Function_evaluate(
/* in */ myProject_Function self,
/* in */ double x,
/* out */ sidl_BaseInterface *_ex)
{
*_ex = 0;
{
/* DO-NOT-DELETE splicer.begin(myProject.Function.evaluate) */
return 4.0 / (1.0 + x * x);
/* DO-NOT-DELETE splicer.end(myProject.Function.evaluate) */
}
}
Now in the same file just above the evaluate method,
find the second method for the FunctionPort
init method:
/*
* Method: init[]
*/
#undef __FUNC__
#define __FUNC__ "impl_myProject_Function_init"
#ifdef __cplusplus
extern "C"
#endif
void
impl_myProject_Function_init(
/* in */ myProject_Function self,
/* in array<double> */ struct sidl_double__array* params,
/* out */ sidl_BaseInterface *_ex)
{
*_ex = 0;
{
/* DO-NOT-DELETE splicer.begin(myProject.Function.init) */
/* nothing to do. */
/* DO-NOT-DELETE splicer.end(myProject.Function.init) */
}
}
We don't have any initialization for this simple example, so we just eliminate the code that throws the exception for running the method.
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited.
Trying to edit file /data/user1/myProject/components/myProject.Function/myProject_Function_Impl.c
$
Similarly change integrate in Integrator with:
$bocca edit -i Integrator integrate/* * Method: integrate[] */ #undef __FUNC__ #define __FUNC__ "impl_myProject_Integrator_integrate" #ifdef __cplusplus extern "C" #endif double impl_myProject_Integrator_integrate( /* in */ myProject_Integrator self, /* in */ double lowBound, /* in */ double upBound, /* in */ int32_t count, /* out */ sidl_BaseInterface *_ex) { *_ex = 0; { /* DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate) */ /* Insert-Code-Here {myProject.Integrator.integrate} (integrate method) */ /* DO-DELETE-WHEN-IMPLEMENTING exception.begin() */ /* * This method has not been implemented. */ SIDL_THROW(*_ex, sidl_NotImplementedException, "This method has not been implemented"); EXIT:; /* DO-DELETE-WHEN-IMPLEMENTING exception.end() */ /* DO-NOT-DELETE splicer.end(myProject.Integrator.integrate) */ } }
Remove this boilerplate exception code and insert an implementation of the
Trapezoid rule for integration that uses the FunctionPort:
/*
* Method: integrate[]
*/
#undef __FUNC__
#define __FUNC__ "impl_myProject_Integrator_integrate"
#ifdef __cplusplus
extern "C"
#endif
double
impl_myProject_Integrator_integrate(
/* in */ myProject_Integrator self,
/* in */ double lowBound,
/* in */ double upBound,
/* in */ int32_t count,
/* out */ sidl_BaseInterface *_ex)
{
*_ex = 0;
{
/* DO-NOT-DELETE splicer.begin(myProject.Integrator.integrate) */
gov_cca_Port port = NULL;
gov_cca_Services services = NULL;
sidl_BaseInterface throwaway_excpt = NULL;
sidl_BaseInterface dummy_excpt = NULL;
struct myProject_Integrator__data *pd = NULL;
const char *errMsg = NULL;
double retval = 0.0;
myProject_FunctionPort integrateThis = NULL;
/* integrateThis non-null if specific uses port obtained. */
int integrateThis_fetched = FALSE;
/* integrateThis_fetched true if releaseport is needed for this port. */
pd = myProject_Integrator__get_data(self);
if (pd == NULL) {
SIDL_THROW(*_ex, sidl_SIDLException,
"NULL object data pointer in myProject.Integrator.integrate()");
}
services = pd->d_services;
if (services == NULL) {
SIDL_THROW(*_ex, sidl_SIDLException,
"NULL pd->d_services pointer in myProject.Integrator.integrate()");
}
/* Use a myProject.IntegratorPort port with port name integrateThis */
port =
gov_cca_Services_getPort(services,"integrateThis", _ex); SIDL_CHECK(*_ex);
integrateThis_fetched = TRUE;
/* even if the next cast fails, must releasePort. */
errMsg="myProject.Integrator: Error casting integrateThis to FunctionPort";
integrateThis = gov_cca_Services__cast2(port,
"myProject.FunctionPort",
_ex); SIDL_CHECK(*_ex);
gov_cca_Port_deleteRef(port, _ex); port = NULL; SIDL_CHECK(*_ex);
{
double h;
double sum = 0.0;
double left, right, fvalueleft, fvalueright;
int i;
h = (upBound - lowBound) / (1.0*count);
printf("Evaluating from %g to %g by %d\n",lowBound ,upBound, count);
for (i = 1; i <= count; i++){
left = lowBound + (i - 1) * h;
fvalueleft = myProject_FunctionPort_evaluate(integrateThis,
left,_ex); SIDL_CHECK(*_ex);
right = lowBound + i * h;
fvalueright = myProject_FunctionPort_evaluate(integrateThis,
right,_ex); SIDL_CHECK(*_ex);
sum += (fvalueleft + fvalueright);
}
retval = h * sum/2.0;
printf("IP returning %g\n",retval);
}
EXIT:; /* target point for normal and error cleanup. do not delete. */
/* release integrate */
if (integrateThis_fetched) {
integrateThis_fetched = FALSE;
gov_cca_Services_releasePort(services,"integrateThis",&throwaway_excpt);
if ( throwaway_excpt != NULL) {
errMsg= "myProject.Integrator: Error calling"
" releasePort(\"integrate\"). Continuing.";
myProject_Integrator_checkException(self, throwaway_excpt, errMsg,
FALSE, &dummy_excpt);
}
if (integrateThis != NULL) {
myProject_FunctionPort_deleteRef(integrateThis, &throwaway_excpt);
errMsg = "Error in myProject_FunctionPort_deleteRef"
" for myProject.Function port integrateThis";
myProject_Integrator_checkException(self, throwaway_excpt, errMsg,
FALSE, &dummy_excpt);
integrateThis = NULL;
}
}
return retval;
/* DO-NOT-DELETE splicer.end(myProject.Integrator.integrate) */
}
}
We see the usual output when no other sources depend on the one just edited.
Trying to edit file /data/user1/myProject/components/myProject.Integrator/myProject_Integrator_Impl.c
$
Finally for the Driver component
we must implement the GoPort details to get things going.
Bocca will take you to the generated method, which looks like:
$bocca edit -i Driver go/* * * Execute some encapsulated functionality on the component. * Return 0 if ok, -1 if internal error but component may be * used further, and -2 if error so severe that component cannot * be further used safely. */ #undef __FUNC__ #define __FUNC__ "impl_myProject_Driver_go" #ifdef __cplusplus extern "C" #endif int32_t impl_myProject_Driver_go( /* in */ myProject_Driver self, /* out */ sidl_BaseInterface *_ex) { *_ex = 0; { /* DO-NOT-DELETE splicer.begin(myProject.Driver.go) */ /* User action portion is in the middle at the next Insert-UserCode-Here line. */ /* Insert-User-Declarations-Here */ /* Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoProlog) */ int bocca_status = 0; /* The user's code should set bocca_status 0 if computation proceeded ok. // The user's code should set bocca_status -1 if computation failed but might // succeed on another call to go(), e.g. when a required port is not yet connected. // The user's code should set bocca_status -2 if the computation failed and can // never succeed in a future call. // The user's code should NOT use return in this function; // Exceptions that are not caught in user code will be converted to status -2. */ gov_cca_Port port = NULL; gov_cca_Services services = NULL; sidl_BaseInterface throwaway_excpt = NULL; sidl_BaseInterface dummy_excpt = NULL; struct myProject_Driver__data *pd = NULL; const char *errMsg = NULL; myProject_IntegratorPort integrate = NULL; /* non-null if specific uses port obtained. */ int integrate_fetched = FALSE; /* true if releaseport is needed for this port. */ pd = myProject_Driver__get_data(self); if (pd == NULL) { SIDL_THROW(*_ex, sidl_SIDLException, "NULL object data pointer in myProject.Driver.go()"); } services = pd->d_services; if (services == NULL) { SIDL_THROW(*_ex, sidl_SIDLException, "NULL pd->d_services pointer in myProject.Driver.go()"); } /* Use a myProject.IntegratorPort port with port name integrate */ port = gov_cca_Services_getPort(services,"integrate", &throwaway_excpt); if (throwaway_excpt != NULL) { port = NULL; errMsg="go() getPort(integrate) failed."; myProject_Driver_checkException(self, throwaway_excpt, errMsg, FALSE, &dummy_excpt); /* we will continue with port NULL (never successfully assigned) and set a flag. */ BOCCA_FPRINTF(stderr, "myProject.Driver: Error calling getPort(\"integrate\") at %s:%d. Continuing.\n", __FILE__ , __LINE__ -8 ); } if ( port != NULL ) { integrate_fetched = TRUE; /* even if the next cast fails, must releasePort. */ errMsg="myProject.Driver: Error casting gov.cca.Port integrate to type myProject.IntegratorPort"; integrate = myProject_IntegratorPort__cast(port, _ex); SIDL_CHECK(*_ex); gov_cca_Port_deleteRef(port,_ex); port = NULL; SIDL_CHECK(*_ex); } /* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoProlog) */ /* When this block is rewritten by the user, we will not change it. All port instances should be rechecked for NULL before calling in user code. Not all ports need be connected in arbitrary use. The port instance names used in registerUsesPort appear as local variable names here. 'return' should not be used here; set bocca_status instead. */ /* Insert-UserCode-Here {myProject.Driver.go} */ /* BEGIN REMOVE ME BLOCK */ BOCCA_FPRINTF(stderr, "USER FORGOT TO FILL IN THEIR GO FUNCTION %s:%d.\n",__FILE__,__LINE__); /* END REMOVE ME BLOCK */ /* If unknown exceptions in the user code are tolerable and restart is ok, set bocca_status -1 instead. -2 means the component is so confused that it and probably the component or application should be destroyed. */ EXIT:; /* target point for normal and error cleanup. do not delete. */ /* Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoEpilog) */ /* release integrate */ if (integrate_fetched) { integrate_fetched = FALSE; gov_cca_Services_releasePort(services,"integrate",&throwaway_excpt); if ( throwaway_excpt != NULL) { errMsg= "myProject.Driver: Error calling releasePort(\"integrate\"). Continuing."; myProject_Driver_checkException(self, throwaway_excpt, errMsg, FALSE, &dummy_excpt); } if (integrate != NULL) { myProject_IntegratorPort_deleteRef(integrate, &throwaway_excpt); errMsg = "Error in myProject_IntegratorPort_deleteRef for myProject.Driver port integrate"; myProject_Driver_checkException(self, throwaway_excpt, errMsg, FALSE, &dummy_excpt); integrate = NULL; } } /* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoEpilog) */ /* Insert-User-Exception-Cleanup-Here */ return bocca_status; /* DO-NOT-DELETE splicer.end(myProject.Driver.go) */ } }
Find the REMOVE block within the go method implementation, delete it,
and insert the numerical logic needed to use the integrator.IntegratorPort port.
Local variables needed are put in the same place with the code.
As indicated in the code comments, each uses port appears
as a local variable with the name of the port.
The go subroutine will be called by the
framework when the component's run button (the name of this
particular GoPort instance) is pushed in the GUI. Bocca
generates the default fetching of the IntegratorPort that the
Driver is connected to. We just have to use it to compute the
integral and return the proper value for bocca_status.
/*
*
* Execute some encapsulated functionality on the component.
* Return 0 if ok, -1 if internal error but component may be
* used further, and -2 if error so severe that component cannot
* be further used safely.
*/
#undef __FUNC__
#define __FUNC__ "impl_myProject_Driver_go"
#ifdef __cplusplus
extern "C"
#endif
int32_t
impl_myProject_Driver_go(
/* in */ myProject_Driver self,
/* out */ sidl_BaseInterface *_ex)
{
*_ex = 0;
{
/* DO-NOT-DELETE splicer.begin(myProject.Driver.go) */
/* Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoProlog) */
int bocca_status = 0;
/* The user's code should set bocca_status 0 if computation proceeded ok.
// The user's code should set bocca_status -1 if computation failed but might
// succeed on another call to go(), e.g. when a required port is not yet connected.
// The user's code should set bocca_status -2 if the computation failed and can
// never succeed in a future call.
// The user's code should NOT use return in this function;
// Exceptions that are not caught in user code will be converted to status -2.
*/
gov_cca_Port port = NULL;
gov_cca_Services services = NULL;
sidl_BaseInterface throwaway_excpt = NULL;
sidl_BaseInterface dummy_excpt = NULL;
struct myProject_Driver__data *pd = NULL;
const char *errMsg = NULL;
myProject_IntegratorPort integrate = NULL; /* non-null if specific uses port obtained. */
int integrate_fetched = FALSE; /* true if releaseport is needed for this port. */
pd = myProject_Driver__get_data(self);
if (pd == NULL) {
SIDL_THROW(*_ex, sidl_SIDLException, "NULL object data pointer in myProject.Driver.go()");
}
services = pd->d_services;
if (services == NULL) {
SIDL_THROW(*_ex, sidl_SIDLException, "NULL pd->d_services pointer in myProject.Driver.go()");
}
/* Use a myProject.IntegratorPort port with port name integrate */
port = gov_cca_Services_getPort(services,"integrate", &throwaway_excpt);
if (throwaway_excpt != NULL) {
port = NULL;
errMsg="go() getPort(integrate) failed.";
myProject_Driver_checkException(self, throwaway_excpt, errMsg, FALSE, &dummy_excpt);
/* we will continue with port NULL (never successfully assigned) and set a flag. */
BOCCA_FPRINTF(stderr, "myProject.Driver: Error calling getPort(\"integrate\") at %s:%d. Continuing.\n",
__FILE__ , __LINE__ -8 );
}
if ( port != NULL ) {
integrate_fetched = TRUE; /* even if the next cast fails, must releasePort. */
errMsg="myProject.Driver: Error casting gov.cca.Port integrate to type myProject.IntegratorPort";
integrate = myProject_IntegratorPort__cast(port, _ex); SIDL_CHECK(*_ex);
gov_cca_Port_deleteRef(port,_ex); port = NULL; SIDL_CHECK(*_ex);
}
/* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoProlog) */
/* When this block is rewritten by the user, we will not change it.
All port instances should be rechecked for NULL before calling in user code.
Not all ports need be connected in arbitrary use.
The port instance names used in registerUsesPort appear as local variable
names here.
'return' should not be used here; set bocca_status instead.
*/
if (integrate == NULL) {
bocca_status = -1; /* not connected. skip computation. */
} else {
int count = 100000;
double value = -4;
double lowerBound = 0.0;
double upperBound = 1.0;
fprintf(stdout, "Initvalue = %g\n", value);
value = myProject_IntegratorPort_integrate(integrate, lowerBound, upperBound,
count, _ex); SIDL_CHECK(*_ex);
fprintf(stdout, "Value = %g\n", value);
fflush(stdout);
}
/* If unknown exceptions in the user code are tolerable and restart is ok, set bocca_status -1 instead.
-2 means the component is so confused that it and probably the component or application should be
destroyed.
*/
EXIT:; /* target point for normal and error cleanup. do not delete. */
/* Bocca generated code. bocca.protected.begin(myProject.Driver.go:boccaGoEpilog) */
/* release integrate */
if (integrate_fetched) {
integrate_fetched = FALSE;
gov_cca_Services_releasePort(services,"integrate",&throwaway_excpt);
if ( throwaway_excpt != NULL) {
errMsg= "myProject.Driver: Error calling releasePort(\"integrate\"). Continuing.";
myProject_Driver_checkException(self, throwaway_excpt, errMsg, FALSE, &dummy_excpt);
}
if (integrate != NULL) {
myProject_IntegratorPort_deleteRef(integrate, &throwaway_excpt);
errMsg = "Error in myProject_IntegratorPort_deleteRef for myProject.Driver port integrate";
myProject_Driver_checkException(self, throwaway_excpt, errMsg, FALSE, &dummy_excpt);
integrate = NULL;
}
}
/* Bocca generated code. bocca.protected.end(myProject.Driver.go:boccaGoEpilog) */
/* Insert-User-Exception-Cleanup-Here */
return bocca_status;
/* DO-NOT-DELETE splicer.end(myProject.Driver.go) */
}
}
After quitting the editor the state of the source code tree is updated if there are any dependencies on the edited implementation. Usually there are no dependencies on the implementation file, so bocca does very little after you exit the editor and all you see is the information from the edit command about what file was edited.
Trying to edit file /data/user1/myProject/components/myProject.Driver/myProject_Driver_Impl.c
$
Now remake your project tree to finish the components:
$make# ======================================================================= # No SIDL files in external/sidl, skipping build for external # ======================================================================= # ======================================================================= # Building in ports/, languages: c # ======================================================================= ## Building ports... # ======================================================================= # Building in components/clients/, languages: c # ======================================================================= ## Building clients... # ======================================================================= # Building in components/, languages: c # ======================================================================= [s] Building component myProject.Driver: [s] creating component library: libmyProject.Driver.la ... [s] finished libtooling: components/myProject.Driver/libmyProject.Driver.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.Function: [s] creating component library: libmyProject.Function.la ... [s] finished libtooling: components/myProject.Function/libmyProject.Function.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.Integrator: [s] creating component library: libmyProject.Integrator.la ... [s] finished libtooling: components/myProject.Integrator/libmyProject.Integrator.la ... [s] creating Ccaffeine test script (components/tests/instantiation.gen.rc)... [s] Building component myProject.emptyComponent: doing nothing -- library is up-to-date. Build summary: SUCCESS building myProject.Driver SUCCESS building myProject.Function SUCCESS building myProject.Integrator ### To test instantiation of successfully built components, run 'make check' ### ################ Finished building everything ################# ####### You can run some simple tests with 'make check' #######$
It is good practice to do a make check at this point:
$make checkmake --no-print-directory --no-builtin-rules -C components check ### Test library load and instantiation for the following languages: c Running instantiation tests only Test script: /data/user1/myProject/components/tests/instantiation.gen.rc SUCCESS: ==> Instantiation tests passed for all built components (see /data/user1/myProject/components/tests/instantiation.gen.rc.log). make --no-print-directory --no-builtin-rules check-user$
You should now be able to instantiate these components, assemble them into an application, and run the application, following the same procedures as in Chapter 2, Assembling and Running a CCA Application, and get a result that's reasonably close to π.