Simple Dynamic Loader Library Documentation (v. 1.1.0)
Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

Simple Dynamic Class Loader

The Simple Dynamic Class Loader library implements a dynamic loader facility for the C++ programming language. It allows applications to load dynamic classes, create objects from dynamically loaded classes, and dynamically access data member and member functions of those classes.

Using Dynamic Classes

Using dynamically-loaded class is simple. As a first step, the user must load a class proxy from a dynamic library using the load_class function. As a result, this function returns a pointer to a Class object, which can be used to create objects of the dynamically-loaded class together with special proxy objects, which provide access to data members and member functions on that object. For example:

#include <sdl.h>
//
// loads class Employee from a dynamic library person.so
//
Class * employee_class = load_class("Employee", "person.so");
//
// now you can use employee_class to create "Employee" objects
// and to access their data members and member functions.
//

This example alludes to a class called "Employee" loaded from a dynamic library called "person.so". The employee_class object provides access to a set of constructor functions that can be used to create "Employee" objects. For example:

//
// create an object of type Person
//
Object * antonio = employee_class.new_object("Antonio");
//
// assign value to data member, and call methods 
// of the "Employee" class
// 
antonio->int_attribute("salary") = 100;
antonio->call("add_project", "Siena");

Implementing Dynamic Classes

Implementing a dynamically-loadable class is also pretty simple, and boils down to defining an initialization function that creates all the necessary bindings between member names and actual data members and member functions of the class. This initialization process is illustrated by the following example:

//
// file employee.cc
//
#include <sdl.h>

using namespace sdl;
//
// actual class declaration
//
class Employee {
private:
    // ...
public:
    int salary;
    void add_project(const string & project_name);
    // ...
};

//
// we must also define one or more constructor "helper" functions
//
static Employee * new_employee() {
    return new Employee();
}

//
// now we are ready to define the initialization function for the
// Employee class
//
extern "C" Class * init_Employee() {

    // first we create a "wrapper" for our Employee class
    ConcreteClass<Employee> * e = new ConcreteClass<Employee>();

    // then we add one or more constructor functions
    e->set_constructor(&new_employee);

    // then we add zero or more data members and/or member functions
    e->bind("salary", &Employee::salary);
    e->bind("add_project", &Employee::add_project);

    // finally, we return the class wrapper
    return e;
}

This code must then be compiled into a dynamically loadable module, which must export the initialization function. The compilation for command might look like this:

g++ -I/opt/sdl/include -c employee.cc -fPIC -DPIC -o employee.o
g++ -shared employee.o -L/opt/sdl/lib -lsdl -o employee.so

The compilation of loadable modules are very much system-dependent, and are therefore outside the scope of this documentation. For more information on compiling dynamically-loadable modules, please consult the libtool utility.

Obviously, the initialization mechanism used by this library is very similar to that of many other modular systems. The main idea is to hook into the dynamically-loaded class through an initialization function, which will be loaded by the operating system's dynamic loader, and executed by SDL. In particular, SDL adopts an initialization scheme whereby the initialization function is directly responsible for returning an interface to the dynamically-loaded class. So, the initialization function must be programmed as follows:

Notice that the class-name used for the initialization function does not have to be the same as the actual class name (passed as a parameter to the ConcreteClass template). Similarly, the binding functions do not require that the name of the data members or member functions be consistent with the actual data member or member function. However, it is sensible practice to be consistent with those names.