nidas  v1.2-1520
Public Types | Static Public Member Functions | Static Public Attributes | List of all members
nidas::core::DOMObjectFactory Class Reference

Class that supports creating instances of DOMable objects from a string containing the class name of the object to be created. More...

#include <DOMObjectFactory.h>

Public Types

typedef DOMabledom_object_ctor_t ()
 Prototype of the creator function. More...
 

Static Public Member Functions

static DOMablecreateObject (const std::string &classname) throw (nidas::util::Exception)
 Create a DOMable object given its classname, by looking up and executing its creator function, typically from a shared library. More...
 

Static Public Attributes

static const char * soVersionSuffix = ".so.1"
 When searching for libraries based on the class name, add this suffix to the name. More...
 

Detailed Description

Class that supports creating instances of DOMable objects from a string containing the class name of the object to be created.

Classes can be dynamically loaded from shared libraries.

Member Typedef Documentation

typedef DOMable* nidas::core::DOMObjectFactory::dom_object_ctor_t()

Prototype of the creator function.

Member Function Documentation

DOMable * DOMObjectFactory::createObject ( const std::string &  classname)
throw (nidas::util::Exception
)
static

Create a DOMable object given its classname, by looking up and executing its creator function, typically from a shared library.

In order to be created via this method, an object's class must have the following characteristics:

  1. Must be derived from class DOMable
  2. An extern "C" function, with prototype DOMable* create_XXXX() must exist (where XXXX is based on the class name). This function must returns a pointer to a new instance of the class. This function can be defined with the NIDAS_CREATOR_FUNCTION() or NIDAS_CREATOR_FUNCTION_NS() macros found in DOMable.h.
  3. The C function is called without arguments, so typically it must call a no-arg constructor for the class. If the above macros are used, a no-arg constructor must exist.

If it were possible to know how C++ mangles the name of a constructor then we could dynamically lookup and execute the default constuctor directly. There isn't a standard for name mangling and I don't know of an API for determining a mangled name, so we create and lookup a C creator function using our own mangling scheme.

For example, if the following class exists in a shareable library, and is derived from DOMable, with a no-arg constructor: nidas::dynld::MyNameSpace::MyClass there then must also be an extern "C" creator function called: create_nidas_dynld_MyNamespace_MyClass The C function can be defined with this macro: NIDAS_CREATOR_FUNCTION_NS(MyNameSpace,MyClass) The classname string argument passed to this createDOMObject() method doesn't contain the leading "nidas::dynld" namespace qualifier, and can be specified in C++ style with "::" delimiters: "MyNameSpace::MyClass" or Java style, with "." delimiters: "MyNameSpace.MyClass"

If the class is in the nidas::dynld namespace, the example above becomes: nidas::dynld::MyClass Extern "C" function: create_nidas_dynld_MyClass Macro to define the C function: NIDAS_CREATOR_FUNCTION(MyClass) classname argument to this method: "MyClass"

The name of the creator function is mangled from the classname argument as follows. The given classname is converted by appending it to nidas_dynld_, and all occurrences of double-colons (::) and periods (.) are replaced with * underscores (_). Then create_ is prepended to the converted class name.

The extern "C" function can be either statically linked in the program, or in a shareable library. createObject() attempts to resolve the extern "C" function symbol via the following search:

  1. Lookup the symbol within the program and the currently loaded dynamic libraries, by calling DynamicLoader::lookup(const std::string& name).
  2. If that fails, look for a shared library named after the converted class name, by passing the converted name with a .so suffix to DynamicLoader::lookup(library,name). Using the first example above, the dynamic loader would look for a library called nidas_dynld_MyNameSpace_MyClass.so.
  3. Then look for shared libraries by successively removing trailing portions of the converted name delimited by underscores, prepending lib to the name, and appending soVersionSuffix. Using the first example the loader would search the following libraries in order:
    1. libnidas_dynld_MyNameSpace.so.1
    2. libnidas_dynld.so.1 assuming that soVersionSuffix was set to ".so.1" in this class.

After being created by this method, then the attributes of the object are typically filled in from an XML DOM element via virtual nidas::core::DOMable::fromDOMElement() method.

References DLOG, nidas::core::DynamicLoader::getInstance(), nidas::core::DynamicLoader::lookup(), and nidas::util::Exception::what().

Referenced by nidas::core::IOChannel::createIOChannel(), nidas::core::VariableConverter::createVariableConverter(), nidas::core::DSMServer::fromDOMElement(), nidas::core::DSMService::fromDOMElement(), nidas::core::DSMConfig::fromDOMElement(), nidas::core::SampleIOProcessor::fromDOMElement(), nidas::core::Project::fromDOMElement(), and nidas::core::DSMConfig::sensorFromDOMElement().

Member Data Documentation

const char * DOMObjectFactory::soVersionSuffix = ".so.1"
static

When searching for libraries based on the class name, add this suffix to the name.

Typically something like ".so.1". This may need more thought. The idea is not to use just ".so", without a version number, since that typically refers to symbolic links found only in -devel packages. Would be nice for this to be set somehow by the build system.


The documentation for this class was generated from the following files: