DynObj - Dynamic Binary Runtime Plugin Objects Hosted by:
SourceForge.net Logo

Instantiating Objects

By default, both the host and a plugin is free to instantiate objects. This can happen in some different ways: Also, at library load time, there is the possibility of passing a reference to an object to the library and receiving one in return (strictly speaking not instantiation):

Instantiating from a loaded library

Libraries are loaded using the DynObjLib class, either directly or indirectly through, doRunTime::LoadLib().

Suppose we have a plugin library named TestPlugin and want to create an object implementing TestI with type ID TEST_TYPE_ID:

DynObjLib *plib = /* Loaded library from somewhere */;
void *pobj = plib->Create( NULL, TEST_TYPE_ID, NULL );
TestI *pti = (TestI*)pobj;

This is a low level way of doing it and we have to cast ourselves.

Instantiating using doRunTimeI

The doRunTimeI interface gives access to a global singleton which provides shared functionality to host and plugins. It can also be used to manage open libraries and to instantiate objects:

TestI *pti = DORT.Create<TestI>("TestPlugin",NULL);

It ends up simpler and we don't need to do any type casts. DORT is a macro returning a reference to the doRunTime singleton, for both applications and plugins.

Creating with do_new<T>()

We can also use a syntax close to that of C++ new:

TestI *pti = do_new<TestI>();

DynObj will select the first library that is registered as capable of instantiating this interface. This is most useful for interfaces that are only intended to have a single implementation (one-to-one interface).

Instantiating using global declarations

In a module implementing an interface, there is nothing stopping us from using global instances of the implementation, and exposing this object. Suppose we want to expose a string converter (StrConvI) we're implementing in a library:
  • // %% DYNOBJ class(DynI) bases(StrConvI,NotifierI)
    class FastStrConv : public StrConvI, public Notifier {
    • // Convert from UTF8 string to local 8 bit code page.
      virtual int docall ToLocal8Bit( const char* pu8_str, DynArrChar& out,
      • const char* pu8_end=NULL ){
        // Implementation
      }
      // More implementation...
    };

    static FastStrConv g_the_fast_str_conv; // Global instance

    extern "C" SYM_EXPORT doModuleData* InitDynLib( DynI* pdi_init ){
    • // Make our object locatable to others
      DORT.ObjectPublish( "fast_str_conv", g_the_fast_str_conv );
      return 0;
    }
We use the DoRunTimeI::ObjectPublish() function to enable others to lookup our converter.

Note: We add Notifier to our base class list to enable our object to be safeky tracked. Otherwise, the ObjectPublish function may fail (it only allows references to trackable objects). In this way, users of FastStrConv are safe, even if this plugin is unexpectedly unloaded.

As parameter or return value at library load time

At library load time, it is possible to pass an object to the library being loaded and to receive an object reference in return. Using doRunTime we do:

DynI *pdi_init = /* Get init object from somewhere */;
DynI *pdi_from_lib = DORT.LoadLib( "TestPlugin", pdi_init, 0 );

At a lower level, using DynObjLib directly, this is the way:
  • DynI *pdi_init = /* Get init object from somewhere */;
    DynObjLib *plib = new DynObjLib("TestPlugin",false);
    DynI *pdi_from_lib = NULL;
    if( plib->GetState()>=DynObjLibI::Loaded )
    • pdi_from_lib = plib->InitDynLib( pdi_init );
This is a practical way of establishing some shared state between a host and a plugin. At the library side, a small trick is needed to return a reference, since the default library init function returns only an integer:
  • // %% DYNOBJ class(DynI) bases(StrConvI,NotifierI)
    class FastStrConv : public StrConvI, public Notifier {
    • // Class body, see above
    };

    static FastStrConv g_the_fast_str_conv; // Global instance

    extern "C" SYM_EXPORT doModuleData* InitDynLib( DynI* pdi_init ){
    • // Provide a directly returned value
      g_do_lib_impl._pdi_from_init = &g_the_fast_str_conv;
      return 0;
    }
The variable g_do_lib_impl (of type doModuleData) contains 'meta-data' about the library. We use it to provide a return value.

Note: Both the object passed to the library init function and the one returned from it should be trackable. The simplest way to do that is to add Notifier or GNotifier to the base class list (see object ownership).