SharedLibraries mit Linux programmieren und nutzen

Hallo zusammen!

Mit C/C++ möchte ich gerne unter Linux mein Programm mittels Shared Libraries dynamischer gestalten. Zum einen sollen Nutzer eigene Plugins einbinden dürfen und zum anderen sollen bestimmte Programmmodule in Shared Libraries ausgelagert werden um das Programm besser warten zu können. Mit Google bin ich schon etwas vorangekommen.
Meine Shared Library zum üben sieht wie folgt aus:

#include

int dll_function(char *message){
printf(„dll: %s\n“, message);
return 0;
}

Die Library (im folgendem nur noch Lib) bekommt einen String übergeben den diese ausgibt. Übersetzen tue ich das Programm wie folgt:
gcc -fpic -c dll.c
gcc -shared -o testlib.so dll.o
Auf diese –soname Geschichte habe ich bewusst verzichtet *, da ich die Libs nur für mein Programm bereitstellen möchte und darum nicht in /opt, /usr/local oder sonst wo brauche.

Diese Lib möchte ich nun in mein Programm einbinden. Darüber hinaus soll mit dynamic linking (#include ) der Nutzer das Programm selbst erweitern können. Der Einfachheit halber verwende ich dafür die gleiche Lib dll.so. Allerdings konnte ich auf keinem der beiden Wege das Programm zum Laufen bekommen. Hierzu mein Vorgehen und die Fehlermeldungen:

#include
int dll_function(char *message);

int main(int argc, char *argv[]){
dll_function („hello world“);
printf(„main-programm is running …\n“);
return 0;
}

Das habe ich dann mit gcc main.c dll.so warnungs- und fehlerfrei übersetzt und beim Ausführen folgende Meldung erhalten:
./a.out: error while loading shared libraries: dll.so: cannot open shared object file: No such file or directory
main.c und dll.so befinden sich im gleichen Verzeichnis und haben beide Lese- und Schreibrecht für meinen Benutzer.

#include
#include
typedef void (*send_message)();

int main(int argc, char *argv[]){
void *lib = dlopen(„dll.so“, RTLD_NOW);
if(!lib){
printf(„ERROR: can’t load dll.so\n“);
eturn -1;
}
send_message dll = (send_message)dlsym(lib, „dll_function“);
dll(„hello world“);
rintf(„main-programm is running …\n“);
dlclose(lib);
return 0;
}

Hier gibt es schon beim Übersetzen Probleme:
/tmp/ccS4ndqD.o(.text+0x1a): In function main': undefined reference to dlopen’
/tmp/ccS4ndqD.o(.text+0x4b): In function main': undefined reference to dlsym’
/tmp/ccS4ndqD.o(.text+0x77): In function main': undefined reference to dlclose’
collect2: ld returned 1 exit status
Eine ausführbare Datei wird erst gar nicht erzeugt. Dem Compiler –ldl mitzugeben bringt auch nichts.

Wie leicht zu erkennen ist habe ich nicht wirklich viel Ahnung davon und mehr durch ausprobieren der verschiedenen Internettutorials eine Lösung zu finden versucht. Meine Frage ist darum auch „ganz kurz“: Wie geht es richtig, also so das es funktioniert?

Grüße
C. Penkwitt

* Auch wenn ich diese Option aktiviert habe, bin ich nicht weiter gekommen!

Hallo,


Meine Shared Library zum üben sieht wie folgt aus:

#include

int dll_function(char *message){
printf(„dll: %s\n“, message);
return 0;
}

Um die Funktion von ausserhalb verwenden zu können, muss sie als extern definiert sein, das sieht wie folgt aus:

extern "C" dll\_function(const char\* message)
{
 printf("dll: %s\n", message);
 return 0;
}

Diese Lib möchte ich nun in mein Programm einbinden. Darüber
hinaus soll mit dynamic linking (#include ) der
Nutzer das Programm selbst erweitern können.

int dll_function(char *message);

Wenns dynamisch GELADEN wird, also zur Laufzeit geladen werden soll, darf dein Compiler die Funktion garnicht kennen! Also weg mit der Zeile da oben :wink:

Ich beschreib jetzt nur mal den weg des dynamischen ladens, da du ja geschrieben hast, du willst verwenden.

void\* hLib = dlopen("./deinelib.so", RTLD\_NOW); // Absoluter Pfad ist besser!
if ( hLib )
{
 typedef int(\*meineDllFunktion)(const char\*);

 meineDllFunktion myFunc = (meineDllFunktion)dlsym(hLib, "dll\_function");
 if ( myFunc ) // NULL-Pointer abprüfen
 myFunc("Hallo Dll-Welt"); 

 dlclose(hLib);
}

Hier gibt es schon beim Übersetzen Probleme:
/tmp/ccS4ndqD.o(.text+0x1a): In function main': undefined reference to dlopen’
/tmp/ccS4ndqD.o(.text+0x4b): In function main': undefined reference to dlsym’
/tmp/ccS4ndqD.o(.text+0x77): In function main': undefined reference to dlclose’
collect2: ld returned 1 exit status
Eine ausführbare Datei wird erst gar nicht erzeugt. Dem
Compiler –ldl mitzugeben bringt auch nichts.

Also normalerweise musst du dem linker -ldl dazugeben, nicht dem compiler …

g++ main.cpp -o testprogramm -ldl

Sollte’s auch erledigen.

Grüße,
Christoph

PS: Ich schreib oft a bisserl wirr :wink:

Hallo Christoph!
Wirr?! Es funktioniert einwandfrei! Vielen Dank!!! Super!
Ich habe noch ein wenig herumprobiert die Lib als echte Shared Lib einzubinden. Zur Vereinfachung habe ich ein Makefile geschrieben und poste jetzt nur die drei Files und danach die Fehlermeldung:

main_shared_lib.c:
#include
// Dies eigentlich in Headerdatei packen
extern void dll_function(char *message);
int main(int argc, char *argv[]){
printf(„main-programm is running …\n“);
dll_function(„hello world“);
return 0;
}

mylib.c:
#include
void dll_function(char *message){
printf(„dll: %s\n“, message);
}

Makefile:
LIB = -fpic -c
SO = -shared
PROG = -L/data/cpenk/Documents/Computergrundlagen/C\ und\ C++/Shared\ Libr
ary/ -lbsp
all: libbsp.so myprog
make clean
libbsp.so: mylib.c
export LD_LIBRARY_PATH=/data/cpenk/Documents/Computergrundlagen/C\
und\ C++/Shared\ Library/:blush:LD_LIBRARY_PATH
gcc $(LIB) mylib.c
gcc $(SO) mylib.o -o libbsp.so
myprog: main_shared_lib.c
gcc $(PROG) main_shared_lib.c -o myprog
clean:
rm *.o

Und das ist das Resultat:
cpenk@linux:~/Documents/Computergrundlagen/C und C++/Shared Library> make
export LD_LIBRARY_PATH=/data/cpenk/Documents/Computergrundlagen/C\ und\ C++/Shared\ Library/:smiley:_LIBRARY_PATH
gcc -fpic -c mylib.c
gcc -shared mylib.o -o libbsp.so
gcc -L/data/cpenk/Documents/Computergrundlagen/C\ und\ C++/Shared\ Library/ -lbsp main_shared_lib.c -o myprog
make clean
make[1]: Entering directory /data/cpenk/Documents/Computergrundlagen/C und C++/Shared Library' rm \*.o make[1]: Leaving directory /data/cpenk/Documents/Computergrundlagen/C und C++/Shared Library’
cpenk@linux:~/Documents/Computergrundlagen/C und C++/Shared Library> ./myprog
./myprog: error while loading shared libraries: libbsp.so: cannot open shared object file: No such file or directory
Das ist das Resultat auf meinem SuSe 10.0 Rechner zu Hause. Auf einem Cluster in der Uni (keine Ahnung welches Linux drauf ist) hat genau dieses Vorgehen mit anderen Pfaden zu Erfolg geführt. Warum funktioniert das so hier nicht? Hast du dazu auch eine Idee?

Grüße
C. Penkwitt

hiho

Setz beim Compilieren des Hauptprogramms ein „-Wl,-rpath,.“ dazu, bzw. den Ort der Bibliothek.
Dieser Pfad wird (info ld) an den Runtime-Linker übergeben.
Normalerweise ist das aber _nicht_ nötig, wenn du denn deine Bibliothek in einen der normalen Pfade (/usr/lib) installieren würdest, was bei normalen Bibliotheken ja der Fall ist.
LD_LIBRARY_PATH geht ebenfalls, muß aber bei _jedem_ Ausführen des Programms gesetzt sein (und ich bin mir einigermaßen sicher, das deine Shell das vom Makefile nicht erbt).

Soweit, mfg TLF