Monday, July 30, 2012

How to Dynamically Load C++ Shared Libraries on Linux

Below is an example how to dynamically load a C++ shared library on Linux. This is the project structure.
|-- include
|   |-- Hello.h
|   `-- IHello.h
|-- src
|   |-- Hello.cpp
|   `-- Main.cpp
`-- wscript
#ifndef IHELLO_H_
#define IHELLO_H_

class IHello {
    virtual void SayHello() const = 0;
    virtual ~IHello() {};

typedef IHello* (*CreateFunc)();
typedef void (*DestroyFunc)(IHello*);

#endif /* IHELLO_H_ */
First, we need to create C-like functions for creating an instance of Hello and destroying it. This is a kind of factory class. Second, we need to add extern "C" to avoid C++ name mangling.
#ifndef HELLO_H_
#define HELLO_H_

#include "IHello.h"

class Hello : public IHello {
    void SayHello() const;
    virtual ~Hello();

#endif /* HELLO_H_ */
#include <iostream>
#include "Hello.h"
using namespace std;

Hello::Hello() {
    cout << "Creating Hello" << endl;

Hello::~Hello() {
    cout << "Destroying Hello" << endl;

void Hello::SayHello() const {
    cout << "Hello World" << endl;

extern "C" IHello* CreateHello() {
    return new Hello;

extern "C" void DestroyHello(IHello* h) {
    delete h;
#include <iostream>
#include <dlfcn.h>
#include "IHello.h"
using namespace std;

int main() {
    void* helloLib = dlopen("./", RTLD_LAZY);
    if (!helloLib) {
        cerr << "Error loading" << endl;
        return 1;

    CreateFunc cf = (CreateFunc) dlsym(helloLib, "CreateHello");
    IHello* hello = cf();

    DestroyFunc df = (DestroyFunc) dlsym(helloLib, "DestroyHello");

    if (dlclose(helloLib)) {
        cerr << "Error closing" << endl;
        return 1;

    return 0;
As you can see in the Main.cpp, we only include IHello.h and not Hello.h (the implementation), which is a pure virtual class. This is something like an interface in Java/C#.
#!/usr/bin/env python

top = '.'
out = 'build'

def options(opt):
def configure(ctx):
def build(ctx):
    ctx.shlib(source='src/Hello.cpp', cxxflags=['-g', '-Wall'],
              target='hello', includes=['include'])
    ctx.program(source='src/Main.cpp', cxxflags=['-g', '-Wall'],
                lib=['dl'], includes=['include'], target='main')

Let's build it now.
waf configure build
cd build
Below is the output.
Creating Hello
Hello World
Destroying Hello

No comments:

Post a Comment