To show the use of both components in an application, we write a test client in the following file structure:
hello/ |-- hello1.0/ |-- test/ | |-- client/ | | |-- client.cc
The client starts with a lot of include and using namespace statements. Note that the included header files reflect the used components.
#include <localComponents/CCM.h> #include <CCM_Local/HomeFinder.h> #include <CCM_Utils/Debug.h> #include <CCM_Local/CCM_Session_Display/Display_gen.h> #include <CCM_Local/CCM_Session_Hello/Hello_gen.h> #include <CCM_Local/CCM_Session_Display/DisplayHome_gen.h> #include <CCM_Local/CCM_Session_Hello/HelloHome_gen.h> using namespace std; using namespace CCM_Utils; using namespace CCM_Local; using namespace CCM_Session_Display; using namespace CCM_Session_Hello;
In the main function, after setting the debugging mode, both component homes are registered at the home finder.
int main ( int argc, char *argv[] ) { // Set debugging mode Debug::set_global(true); // Get in instance of the local HomeFinder and register component homes localComponents::HomeFinder* homeFinder = HomeFinder::Instance ( ); try { homeFinder->register_home( create_DisplayHomeAdapter(), "DisplayHome" ); homeFinder->register_home( create_HelloHomeAdapter(), "HelloHome" ); } catch ( ... ) { cout << "Aut'sch: when register homes!" << endl; return -1; }
Now, we can use the home finder to find the homes by name. We create an instance of each component, get references the the component's facets and connect the facet of Display with the receptacle of Hello. Note that both ports are defined by the same LCD interface.
try { // Find component home SmartPtr<DisplayHome> myDisplayHome (dynamic_cast<DisplayHome*> ( homeFinder->find_home_by_name ( "DisplayHome").ptr ())); SmartPtr<HelloHome> myHelloHome (dynamic_cast<HelloHome*> ( homeFinder->find_home_by_name ( "HelloHome").ptr ())); // Create component instance SmartPtr<Hello> myHello = myHelloHome.ptr()->create(); SmartPtr<Display> myDisplay = myDisplayHome.ptr()->create(); // Get facet references and connect facets to receptacles SmartPtr<CCM_Console> console = myHello.ptr()->provide_console(); SmartPtr<CCM_LCD> lcd = myDisplay.ptr()->provide_lcd(); myHello.ptr()->connect_lcd(lcd); // Configure the component's attribute myDisplay.ptr()->prompt("-=> "); // Component configuration finished myHello.ptr()->configuration_complete(); myDisplay.ptr()->configuration_complete();
The test client has build an component assembly of two components in memory and can use its functionality.
// Call operations on the component assembly cout << "Display Version = " << myDisplay.ptr()->getComponentVersion() << endl; cout << "Hello Version = " << myHello.ptr()->getComponentVersion() << endl; console.ptr()->println("Hello from the client");
To tear the component assembly town, we disconnect the ports and remove the component instances from memory. We also unregister the component's homes from the home finder.
// Disconnect component ports myHello.ptr()->disconnect_lcd(); // Destroy component instances myDisplay.ptr()->remove(); myHello.ptr()->remove(); // Unregister component homes homeFinder->unregister_home("DisplayHome"); homeFinder->unregister_home("HelloHome"); } catch ( localComponents::HomeNotFound ) { cout << "Aut'sch: can't find a home!" << endl; return -1; } catch ( ... ) { cout << "Aut'sch: there is something wrong!" << endl; return -1; } return 0; }
We build the test client with Confix and run the binary:
~/hello/test> confix.py --bootstrap --configure \ --make --targets=install --profile=ccmtools ~/hello/test> test_client_client
Isn't it cool?
We have run a test client that uses two components which are connected via facet
and receptacle to build a component assembly.
In the same way, we can create more complex assemblies that form a real
component based application as well.
Look at the printed debugging information to trace the execution thread of the test client. We can also switch off the messages by setting the debugging mode in the main function to false.
2003-11-09