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:
-
In der Klasse FooHallo gibt die Methode msg() den Text Hallo und
-
in der Klasse FooWelt gibt die Methode msg() den Text Welt aus.
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
#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 <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 <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 <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>