Content

Mini-Beispiel zur Verwendung einer Shared-Library

In diesem Beispiel wird eine abstrakte Basis-Klasse Foo definiert. Diese besitzt genaue eine Methode msg(). Zwei Implementierungen für diese Klasse werden vorgestellt:

Im Testprogramm testit wird eine Shared-Library geladen. Der Name wird beim Aufruf des Programmes als Parameter übergeben. Genauso gut könnte der Name der Shared-Library aber auch mittels std::cin zur Laufzeit in einen String eingelesen werden. In testit wird dann die Funktion construct in der Shared-Library aufgerufen, um einen Funktionszeiger auf den Constructor der Foo-Implementierung zu bekommen. Gelingt dies, so wird der Constructor aufgerufen und ein Objekt der Foo-Implementierung erzeugt. Für diese wird dann die msg() Methode aufgerufen.

Coming up next

Auf der nächsten Seite (next) zeigen wir ein Beispiel, bei dem es notwendig ist, das Testprogramm mit -rdynamic zu übersetzen.

Die abstrakte Klasse Foo

#ifndef FOO_HPP
#define FOO_HPP

class Foo
{
    public:
        virtual
            void
            msg() const = 0;
};

#endif

Das Test-Programm

Beachtet, dass im Test-Programm nur die abstrakte Klasse Foo bekannt sein muss. Es werden keine weiteren Informationen über die konkreten Implementierungen benötigt oder gar verwendet.

#include "foo.hpp"
#include <iostream>
#include <link.h>
#include <string>

typedef Foo *FooConstructor();

int
main(int argc, char **argv)
{
    if (argc!=2) {
        std::cerr << "usage: " << argv[0] << " <shared-lib>" << std::endl;
        return 1;
    }

    void* handle = dlopen(argv[1], RTLD_LAZY | RTLD_LOCAL);
    if (!handle) {
        return 2;
    }
    FooConstructor *constructor = (FooConstructor*) dlsym(handle, "construct");
    if (!constructor) {
        dlclose(handle);
        return 3;
    }
    Foo *foo = constructor();

    foo->msg();
}

Übersetzen des Test-Programmes

$shell> g++ -Wall -std=c++11 -o testit testit.cpp
$shell> 

Foo-Implementierung FooHallo

#include "foo.hpp"
#include <iostream>

class FooHallo
    : public Foo
{
    public:

        void
        msg() const
        {
            std::cout << "Hallo!" << std::endl;
        }
};

// support dynamic loading
extern "C" {

Foo*
construct()
{
    return new FooHallo();
}

// extern "C"

Erzeugen von foo_hallo.so

$shell> g++ -shared -fPIC -Wall -std=c++11 -o foo_hallo.so foo_hallo.cpp
$shell> 

Foo-Implementierung FooWelt

#include "foo.hpp"
#include <iostream>

void
main_msg();

class FooWelt
    : public Foo
{
    public:
        void
        msg() const
        {
            std::cout << "Welt!" << std::endl;
        }
};

// support dynamic loading
extern "C" {

Foo*
construct()
{
    return new FooWelt();
}

// extern "C"

Erzeugen von foo_welt.so

$shell> g++ -shared -fPIC -Wall -std=c++11 -o foo_welt.so foo_welt.cpp
$shell> 

Ausführen des Test-Programmes

$shell> ./testit ./foo_hallo.so
Hallo!
$shell> ./testit ./foo_welt.so
Welt!
$shell>