Click here to Skip to main content
13,548,412 members
Click here to Skip to main content
Add your own
alternative version


39 bookmarked
Posted 7 Aug 2008
Licenced BSD

SOF - An OSGI-like modularization framework for C++

, 24 Sep 2008
Rate this:
Please Sign up or sign in to vote.
The article describes the usage of a modularization framework called SOF.

Sample Image


SOF (Service Oriented Framework) provides an OS independent infrastructure for developing component based software. That means, the framework helps developers to build software systems consisting of modules which are communicating, via clearly defined service interfaces, with other modules of the system. Components can be started and stopped at runtime, and the components are notified about the lifecycle of other components, if necessary. It can be chosen whether the components are loaded locally (here, the component code is linked to the class which starts the framework), or loaded dynamically from shared libraries (UNIX) or dynamic link libraries (Windows), for example. SOF is implemented in standard C++, and the SOF API is very similar to the OSGI API (see OSGI).

Using the code

What does a module consist of?

Each module (also called 'bundle') consists of the following code parts:

  • A class which implements the sof::framework::IBundleActivator interface.
  • One or several service interfaces which can be called by other bundles.
  • Optionally: A class providing an interface for loading a dynamic link library or shared library.
  • Classes implementing the business logic.

The following example describes the implementation of two bundles (called 'bundle1' and 'bundle2') which communicate via a service interface. The first bundle registers a service object of type IMultiplier. The second bundle listens for service objects of type IMultiplier. As soon as a service object of type IMultiplier is available, the second bundle calls the getValue() method of the service object.

The IBundleActivator interface

The IBundleActivator interface provides three methods (destructor, start, stop), which have to be implemented for creating, starting, and stopping a bundle. The example below shows the implementation of the IBundleActivator interface for 'bundle1', whereas the destructor, start, and stop methods are not filled with code yet.

Header file:


#include <span class="code-string">"sof/framework/IBundleActivator.h"</span>
#include <span class="code-string">"sof/framework/IBundleContext.h"</span>

using namespace sof::framework;

class BundleActivator1 : public IBundleActivator
        virtual ~BundleActivator1();
        virtual void start( IBundleContext::ConstPtr context )
        virtual void stop( IBundleContext::ConstPtr context );


#include <span class="code-string">"BundleActivator1.h"</span>

#include <span class="code-string">"sof/instantiation/ObjectCreator.h"</span>

using namespace sof::instantiation;
using namespace sof::framework;

    // Deallocate memory

void BundleActivator1::start(IBundleContext::ConstPtr context) 
    // Add code for registering services and service listeners

void BundleActivator1::stop(IBundleContext::ConstPtr context) 
    // Add code for deregistering services and service listeners

REGISTER_BUNDLE_ACTIVATOR_CLASS( "BundleActivator1", BundleActivator1 )

Only the framework calls the start and stop methods for starting and stopping the bundle. When these methods are called, a parameter of type IBundleContext is passed, which allows communicating with the framework (registering/deregistering services, service listeners etc.). The framework is also responsible for creating an instance of the bundle activator class, before the bundle is started. For this, the type and the name of the bundle activator class (here, BundleActivator1) have to be registered at the framework, by using the REGISTER_BUNDLE_ACTIVATOR_CLASS macro.


Bundles communicate with other bundles via services. Each service class has to implement the IService interface which does not provide any methods. It is only a marker interface. Our interface for the communication between 'bundle1' and 'bundle2' defines only one method which multiplies two integer values and returns the result of the multiplication.

Header file:


#include <span class="code-string">"sof/framework/IService.h"</span>

using namespace sof::framework;

class IMultiplier : public IService
        virtual int multiply( int x, int y ) = 0;


The implementation of the service interface is done in the 'IMultiplierImpl.h' file, which is not shown here.

Registering and deregistering services

After the service interfaces are defined (here, only one interface) and implemented, the code for registering and deregistering the service can be implemented. For this, the IBundleContext instance which is passed to the start and stop methods of the bundle activator class is used. The start method of 'bundle1' creates an instance of the IMultiplierImpl class at first. Then, a Properties object is created, which holds key/value pairs of type string and allows specifying the service object in detail. Finally, the service object is registered at the framework by calling the registerService method of the IBundleContext object. Three parameters have to be passed to the registerService call:

  • The name of the service (typically, the name of the service class)
  • The service object itself
  • The Properties object

After the registration process of the service object, the multiplier can be used by other bundles. For the case that the service object should be no longer available for other bundles, the service can be unregistered, which is done here in the stop method.


#include <span class="code-string">"BundleActivator1.h"</span>

#include <span class="code-string">"sof/instantiation/ObjectCreator.h"</span>
#include <span class="code-string">"sof/framework/Properties.h"</span>

#include <span class="code-string">"IMultiplier.h"</span>
#include <span class="code-string">"IMultiplierImpl.h"</span>

using namespace sof::instantiation;
using namespace sof::framework;

    // Deallocate memory

void BundleActivator1::start(IBundleContext::ConstPtr context) 
    this->service = new IMultiplierImpl();    

    Properties props;
    props.put( "instance", "1" );

    this->serviceReg = context->registerService( "IMultiplier", 
                                        this->service, props ); 

void BundleActivator1::stop(IBundleContext::ConstPtr context) 
    delete this->serviceReg;
    delete this->service;

REGISTER_BUNDLE_ACTIVATOR_CLASS( "BundleActivator1", BundleActivator1 )

Registering and deregistering service listeners

The previous section described how to register a service object. Now, we talk about how registered services can be used by other bundles. For this, you have to create a ServiceTracker object, which expects three parameters in the constructor:

  • The IBundleContext object
  • The name of the service which has to be found (here, the name of the service class)
  • An object implementing the IServiceTrackerCustomizer interface (in the following example, it is implemented by the bundle activator class)

As soon as the startTracking method of the ServiceTracker instance is called, the service tracker begins to listen for registered services of name 'IMultiplier'. If there is a registered service object of name 'IMultiplier' (no matter the service was registered before or after the service tracker was started), the framework notifies the IServiceTrackerCustomizer object (here, the bundle activator which is implementing this interface) of the existing service object, by calling the addingService method. In the addingService method, you can ask for the name or the properties of the found service in order to check whether it is the service object you are interested in. If so, the service object can be retrieved from the service reference and casted to the service interface (IMultiplier). Now, the service can be used. It must be pointed out that the addingService method has to return a boolean value. You have to return true if you are interested in using the found service, otherwise false. For the case that the IMultiplier service is deregistered by the other bundle, the related service trackers are notified by a removedService method call. In order to stop listening for service objects, the stopTracking method of the ServiceTracker object has to be called.


#include <span class="code-string">"BundleActivator2.h"</span>

#include <span class="code-keyword"><iostream></span>

#include <span class="code-string">"sof/instantiation/ObjectCreator.h"</span>

#include <span class="code-string">"IServiceA.h"</span>

using namespace std;
using namespace sof::instantiation;

    // Deallocate memory

void BundleActivator2::start(IBundleContext::ConstPtr context) 
    this->tracker = new ServiceTracker( context, "IMultiplier", this );

void BundleActivator2::stop(IBundleContext::ConstPtr context) 
    delete ( this->tracker );

bool BundleActivator2::addingService( const ServiceReference& ref )
    if ( ref.getServiceName() == "IMultiplier" )
        Properties props = ref.getServiceProperties();
        if ( props.get( "instance" ) == "1" )
            this->service = static_cast<IMultiplier*> ( ref.getService() );
            cout << "[BundleActivator2#addingService] Calling IMultiplier..." << endl;
            int value = this->service->multiply( 47, 11 );
            cout << "[BundleActivator2#addingService] Returned value of IMultiplier: " 
                 << value << endl;
            return true;
            return false;
        return false;

void BundleActivator2::removedService( const ServiceReference& ref )

REGISTER_BUNDLE_ACTIVATOR_CLASS( "BundleActivator2", BundleActivator2 )

Creating bundle libraries

Up till now, we've implemented the code for two bundles. One bundle registers a service object of type IMultiplier, the other bundle listens for this service object and calls it. Now, we want to create two bundle libraries, one library for each bundle. Since this code example ought to be run on the Windows platform, we have to implement a Windows DLL:

Implementation (dll.cpp):

#include <span class="code-keyword"><windows.h></span>

#include <span class="code-keyword"><stdlib.h></span>
#include <span class="code-keyword"><string></span>
#include <span class="code-keyword"><iostream></span>

#include <span class="code-string">"sof/instantiation/ObjectCreator.h"</span>
#include <span class="code-string">"sof/framework/IBundleActivator.h"</span>

#define DLL extern "C" __declspec(dllexport)

using namespace std;
using namespace sof::instantiation;
using namespace sof::framework;

                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
    return TRUE;

DLL IBundleActivator* createObject( const string &className )
    ObjectCreator<IBundleActivator> OC_BUNDLE_ACTIVATOR;
    return OC_BUNDLE_ACTIVATOR.createObject( className );                    

The dllMain method represents the entry point for the DLL where initialization calls (not necessary) can be done. The dllMain method is defined by the Windows platform, and is called when the DLL is loaded. SOF itself requires an implementation of the createObject method which provides the functionality for creating IBundleActivator instances. This 'dll.cpp' file does not have to be changed for the implementation of other bundles. It can always be reused.

project view

The picture above shows a snapshot of the project view in Visual Studio. The first bundle is implemented in the 'sof_examples_bundle1' project, and contains the following files:

  • The header and source file of the bundle activator (BundleActivator1)
  • The interface definition (IMultiplier.h) and implementation (IMultiplierImpl.h) of the service interface
  • The definition of the DLL interface ('dll.cpp')

The project view of the second bundle (project 'sof_examples_bundle2') contains:

  • The bundle activator
  • Only the service interface (IMultiplier.h) (not an implementation of the service)
  • The definition of the DLL interface

Each project can now be built as a Windows DLL, and then there will be two bundle libraries: 'bundle1.dll' and 'bundle2.dll'. The next section describes how the bundles can be started, which is implemented in the 'sof_examples.cpp' file of the 'sof_examples' project.

Starting the framework

For starting the framework, an instance of the class Launcher has to be created (see the 'sof_examples.cpp' file). The Launcher class represents a template based class which allows the specification of a:

  • Threading policy
    • Influences the threading behaviour of the framework.
  • Creation policy
    • Defines the way a bundle is loaded from a library (e.g., Windows DLL, Unix shared library etc.).

In order to keep OS dependent code away from the framework, the threading and creation behaviour can be easily adapted to any Operating System by using this template solution. The framework only provides the SingleThreaded class and the WinDllCreator class as implementations of the threading and creation policies. The SingleThreaded class requires that framework calls (e.g., registering/deregistering services and service listeners) are done in a single thread; otherwise, race conditions can occur. The WinDllCreator class can only be used for the Windows platform, and supports the loading of bundles which are built as Windows DLLs.

After the Launcher class is created, the bundle configuration for each bundle must be specified. A BundleConfiguration contains all the relevant information of a bundle for creating and starting it:

  • The name of the bundle
  • The name of the bundle activator class
  • The directory where the bundle library is located, e.g., '.' for the current directory, or 'c:/temp'
  • The name of the bundle library

Now, the bundle configuration can be passed to the Launcher instance by calling the start method. This is the trigger for starting the framework, and creating and starting the bundle activators.

Main method of 'sof_examples.cpp':

#include <span class="code-keyword"><iostream></span>
#include <span class="code-keyword"><vector></span>

#include <span class="code-string">"sof/framework/Launcher.h"</span>
#include <span class="code-string">"sof/framework/Global.h"</span>
#include <span class="code-string">"sof/config/BundleConfiguration.h"</span>
#include <span class="code-string">"sof/instantiation/win/WinDllCreator.h"</span>
#include <span class="code-string">"sof/util/threading/SingleThreaded.h"</span>

using namespace std;

using namespace sof::framework;
using namespace sof::config;
using namespace sof::util::threading;
using namespace sof::instantiation::win;

int main(int argc, char* argv[])
    Launcher<SingleThreaded,WinDllCreator> launcher;

    // Specifying the bundle configuration
    BundleConfiguration bundle1( "bundle1", "BundleActivator1", 
                                 ".", "sof_examples_bundle1.dll" );
    BundleConfiguration bundle2( "bundle2", "BundleActivator2", 
                                 ".", "sof_examples_bundle2.dll" );

    vector<BundleConfiguration> configuration;
    configuration.push_back( bundle1 );
    configuration.push_back( bundle2 );

    // Starting the framework
    launcher.start( configuration );

    // Starting the administration console
    // for interacting with the framework

    return 0;

The following sequence chart shows the startup procedure in a simplified way:


After the executable file 'sof_examples.exe' is started, both bundles are started, and we can see that 'bundle2' calls the 'multiplier' service of 'bundle1' (see the highlighted lines in the picture below).


As soon as all the configured bundles (here: 'bundle1' and 'bundle2') are started, the SOF console allows entering commands in order to interact with the framework. Please enter 'help' for displaying all the available commands. There are commands for:

  • Showing all the relevant information of a bundle (e.g., registered services, service listeners, and used services):
  • dump_bundle.gif

  • Starting and stopping further bundles.
  • Listing the names of all started bundles:
  • dump_all_bundles.gif


This article gave a small introduction to the SOF framework which provides the following features:

  • It can be configured which bundles ought to be started at framework startup.
  • Software modules can be started and stopped during runtime (via SOF console), so a bundle implementation can be replaced by another one.
  • Loose coupling between modules (bundles): software modules communicate only via service interfaces.
  • The framework can be easily adapted to specific Operating Systems by using templates.

You'll find more documentation on the project's website. Please do not hesitate to give me your opinion about this framework or the article.


  • August 7, 2008 - Created the article.
  • August 9, 2008 - Changed license from GPL to BSD.


This article, along with any associated source code and files, is licensed under The BSD License


About the Author

Software Developer
Germany Germany
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionReferenz Pin
Ingmar Franke22-Sep-13 5:57
memberIngmar Franke22-Sep-13 5:57 
Questionadd license info to source files Pin
Member 898911616-May-12 23:01
memberMember 898911616-May-12 23:01 
AnswerRe: add license info to source files Pin
magr7424-May-12 19:06
membermagr7424-May-12 19:06 
Question[ObjectCreator#createLocalObject] No intantiator for class available Pin
kingswip19-Aug-11 20:49
memberkingswip19-Aug-11 20:49 
AnswerRe: [ObjectCreator#createLocalObject] No intantiator for class available Pin
magr744-Sep-11 17:57
membermagr744-Sep-11 17:57 
GeneralRe: [ObjectCreator#createLocalObject] No intantiator for class available Pin
patoch3127-Aug-12 4:45
memberpatoch3127-Aug-12 4:45 
GeneralIt looks interesting Pin
Cedric Moonen1-Sep-10 20:31
memberCedric Moonen1-Sep-10 20:31 
GeneralAdd a Bundle withtout compiling the main program Pin
batigabriel26-May-10 4:55
memberbatigabriel26-May-10 4:55 
GeneralRe: Add a Bundle withtout compiling the main program Pin
magr7427-May-10 19:32
membermagr7427-May-10 19:32 
QuestionCurrent SOF Development Status? Pin
jonworley5-Apr-10 13:13
memberjonworley5-Apr-10 13:13 
AnswerRe: Current SOF Development Status? Pin
magr746-Apr-10 12:20
membermagr746-Apr-10 12:20 
AnswerRe: Current SOF Development Status? Pin
magr747-Apr-10 23:39
membermagr747-Apr-10 23:39 
GeneralScons build error Pin
JasonLeeHust12-Jan-10 15:36
memberJasonLeeHust12-Jan-10 15:36 
GeneralRe: Scons build error Pin
magr7413-Jan-10 19:47
membermagr7413-Jan-10 19:47 
GeneralRe: Scons build error Pin
JasonLeeHust20-Jan-10 17:15
memberJasonLeeHust20-Jan-10 17:15 
GeneralRe: Scons build error Pin
magr7420-Jan-10 19:46
membermagr7420-Jan-10 19:46 
QuestionOther version project? Pin
xabrooklyn4-Nov-09 15:45
memberxabrooklyn4-Nov-09 15:45 
AnswerRe: Other version project? Pin
magr749-Nov-09 19:51
membermagr749-Nov-09 19:51 
GeneralScons and sof Pin
fboucquez2-Jul-09 9:11
memberfboucquez2-Jul-09 9:11 
GeneralRe: Scons and sof Pin
magr742-Jul-09 21:28
membermagr742-Jul-09 21:28 
QuestionStill maintained? Pin
oliver198127-Jan-09 23:24
memberoliver198127-Jan-09 23:24 
AnswerRe: Still maintained? Pin
magr741-Feb-09 19:19
membermagr741-Feb-09 19:19 
GeneralRe: Still maintained? Pin
sucks12349-May-09 13:00
membersucks12349-May-09 13:00 
GeneralRe: Still maintained? Pin
magr7410-May-09 20:24
membermagr7410-May-09 20:24 
AnswerRe: Still maintained? Pin
magr748-Jul-09 17:48
membermagr748-Jul-09 17:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03-2016 | 2.8.180515.1 | Last Updated 24 Sep 2008
Article Copyright 2008 by magr74
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid