Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 18

Thema: Shared Libs / Object in C++ unter Linux

  1. #1
    Registrierter Benutzer
    Registriert seit
    11.04.2007
    Beiträge
    54

    Shared Libs / Object in C++ unter Linux

    Kurz nee fragende Anmerkung zum Thema Shared Objects in C++ unter Linux

    Nachdem ich das schöne .so Beispiel "cosinus" in C zum laufen gebracht habe.

    Hab ich mir ein Beispiel besorgt, das unter C++ kompiliert werden kann (in Kdevelop)

    Nachdem ja in dem Cosinus Code die so-File direkt ohne ./ oder Verzeichniss angegeben wird,
    dachte ich mir das geht auch ganz einfach mit ner selbst geschriebenen .so File.

    Hier der Code vom Cosinus Beispiel:

    #include <stdio.h>
    #include <dlfcn.h>

    int main(int argc, char **argv) {
    void *handle;
    double (*cosine)(double);
    char *error;

    handle = dlopen ("libm.so", RTLD_LAZY);
    if (!handle) {
    fprintf (stderr, "%s\n", dlerror());
    exit(1);
    }

    cosine = dlsym(handle, "cos");
    if ((error = dlerror()) != NULL) {
    fprintf (stderr, "%s\n", error);
    exit(1);
    }

    printf ("%f\n", (*cosine)(2.0));
    dlclose(handle);
    return 0;
    }

    Kompiliert wird das dann in der Console mit

    gcc -rdynamic -o foo foo.c -ldl

    Wie man sieht steht bei dlopen nur "libm.so" also weder "./libm.so" oder gar "/usr/lib/libm.so"

    Das funktioniert ja, weil die libm.so in dem Library-Verzeichniss des Betriebssystem liegen

    und das Programm dann während der ausführung automatisch in diesem Verzeichniss sucht.


    Nun habe ich folgende File geladen

    (siehe Anhang)

    dann mit

    tar zxvf examples.tar.tar

    entpackt.

    Wenn man sich den Quellcode main.cpp anschaut, sieht man folgende Zeile.

    void* triangle = dlopen("./triangle.so", RTLD_LAZY);

    d.h. die .so File muss sich also dann im lokalen Verzeichniss befinden in dem sich auch die Runfile befindet.

    Nachdem ich alles kompiliert hatte (nicht mit dem mitgeliefertem Make, sondern als Projekt in KDevelop)
    mit einem zusätzlichen Parameter -ldl (da er sonst mit dem dlopen usw total aussteigt)

    (zu finden in KDevelop unter

    Projekt-> Optionen -> Compiler Einstellungen->Linker Schalter->weiter Schalter und dort in dieses Feld -ldl eintragen

    )
    hatte er die Runfile erzeugt und eine File triangle.o

    Diese .o File muss ich ja jetzt noch dynamic shared machen mit folgendem Befehl

    g++ -rdynamic -shared -o triangle.so triangle.o

    nun habe ich eine .so File....

    nun will ich aber die .so File nicht im lokalen Verzeichniss haben, sondern wie die libm.so
    (von oben) im /usr/lib Verzeichniss (Library Verzeichniss des Systems)

    Da ich aber keine Root Rechte besitze in dieses Verzeichniss zu schreiben

    erzeuge ich kurzerhand selbst ein Verzeichniss

    /usr/usr/myaccount/mylibs/

    und setze mit setenv den Library Path darauf

    setenv LD_LIBRARY_PATH /usr/usr/myaccount/mylibs

    eine Überprüfung mit env | grep LIB zeigt mir das der Pfad gesetzt wurde

    wenn ich nun die .so File in das mylibs Verzeichniss verschiebe

    und dann im Quellcode statt "./triangle.so" einfach "triangle.so" schreibe,
    meldet er nachdem das Programm gestartet wurde, das er die Library nicht findet.


    Was mach ich falsch?

    bin hier echt am verzweifeln....
    wieso funktioniert das mit der Standard Lib libm.so , aber mit der selbst geschriebenen im selbst gesetzten Lib-Verzeichniss nicht


    danke schon mal für alle Infos

    UFO



    p.s. habe auch schon mal mittels

    g++ -shared -Wl,-soname,triangle.so.1 -o triangle.so.1.0 triangle.cpp

    mv triangle.so.1.0 /usr/myaccount/mylibs
    mv triangle.so /usr/myaccount/mylibs

    ln -sf /usr/myaccount/mylibs/triangle.so.1.0
    ln -sf /usr/myaccount/mylibs/triangle.so
    ln -sf /usr/myaccount/mylibs/triangle.so.1

    Symbolisch links erzeugt...
    d.h. im lokalen verzeichniss ist dann ein Link namens triangle.so der auf die /usr/myaccount/mylibs/triangle.so verlinkt

    das mag er aber auch nicht... sondern nur wenn ich wieder "triangle.so" in "./trinangle.so" umändere dann funzt das Ding mit dem Link...


    p.p.s. mein Ziel ist es... das die Libs einmal alle kompiliert werden und in ein Verzeichniss abgelegt werden, das als LD_LIBRARY_PATH gesetzt wird,
    d.h. ich will keine Libs oder Verlinkungen drauf in meinem Programmverzeichniss liegen haben

  2. #2
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Hab main.cpp so geändert:
    Code:
    void* triangle = dlopen("triangle.so", RTLD_LAZY);
    Dann triangle.so nach /tmp verschoben und LD_LIBRARY_PATH auf /tmp gesetzt.

    Hat einwandfrei funktioniert

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  3. #3
    Registrierter Benutzer
    Registriert seit
    11.04.2007
    Beiträge
    54

    Angry

    also bei mir klappt das net...

    ich hab etz auch die .so file (keine verlinkung ... die reine .so file) nach /tmp verschoben

    danach mit setenv LD_LIBRARY_PATH /tmp

    den Lib Pfad gesetzt

    (das alles in der console)

    und dann das Programm geändert und kompiliert (in Kdevelop)
    dann in der Console ausgeführt...

    NULL ... nix geht... immer noch Fehlermeldung das er die Library nicht finden kann...

    dann hab ich gemerkt das im Reiter KOnsole in Kdevelop wenn ich env |grep LIB eingeben der neue Pfad /tmp nicht angezeigt wird.. also auch hier nochmal den Pfad gesetzt....

    hab auch nix gebracht... also weder starten von der Konsole als auch aus Kdevelop raus...

    dann hab ich mal den Pfad statt /tmp in /tmp/ geändert...

    wieder überall gesetzt... das brachte auch nix...

    ich bin ehrlich mit meinem Latein am Ende...

    noch irgendwelche Tips?

    danke schon mal

    ufo

  4. #4
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Welche Shell setzt du ein? Bzw, bist du sicher, daß die den setenv Syntax benutzt und nicht wie Bash "export"?

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  5. #5
    Registrierter Benutzer
    Registriert seit
    11.04.2007
    Beiträge
    54
    also wenn ich setenv mache und dann mit env |grep LIB überprüfe dann hat er das in der Cosole auch gemacht... also den Pfad hinzugefügt...

    export gibt es nicht... da schlägt er exports vor...

    export geht nur wenn ich

    bash --login mache...

    is ein Suse 8.1 Pc mit Kernel 2.4.19 -64GB -SMP /i686 an dem ich arbeite...

    bei Kdevelop zeigt er 2.13 an

    bei g++ zeigt er gcc 3.2 an


  6. #6
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Hmm, eigenartig daß SUSE nicht auch eine Bash benutzt.

    Aber wenn es nachweislich mit env | grep gefunden wird, hat das Setzen geklappt.

    Wenn es in dieser Shell dann bei dir trotzdem nicht klappt, ist das schon eigenartig.
    Als root arbeitest du eh nicht, oder?

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  7. #7
    Registrierter Benutzer
    Registriert seit
    11.04.2007
    Beiträge
    54

    Thumbs down

    nee hab keine root rechte...und auch keine change welche zu bekommen... deswegen ja das rumgefummel da mit dem zusätlichen lib verzeichniss und dem setzen... sonst hätte ich ja die Libs ins /usr/lib Verzeichniss gepackt, da sagt aber das System das ich keine Rechte habe...
    echt zum kotzen...

    wenn ich einen ln ... (verweiss) auf die Library setze und diesen verweiss dann in das Programmverzeichniss packe und im Code dann mit "./Library.so" arbeite dann funzt es... aber das funzt auch wenn ich den Pfad nicht setze...
    somit nimmt der nur den Link her...

    wenn ich dann abändere in "Library.so" dann sagt er das er die Lib nicht findet... egal ob jetzt Pfad gesetzt in Bash, normale Console oder im Konsolenfenster von KDevelop...

    traurig traurig... da setzt man Werte bis zum umfallen und Linux beachtet diese gar nicht...

    falls noch jemand nen Tip hat... bitte posten...

    thx UFO

    p.s. nen Neustart benötigt man aber net nicht oder... also nacht setzen der Library... (weil soweit ich weiss löscht der das wieder... also das gesetzte Verzeichniss.. also bei Neustart des Systems)
    Geändert von ufosworld (17-04-2007 um 09:44 Uhr)

  8. #8
    Registrierter Benutzer
    Registriert seit
    18.03.2005
    Beiträge
    211
    und setze mit setenv den Library Path darauf
    setenv LD_LIBRARY_PATH /usr/usr/myaccount/mylibs
    ldconfig hasst aber ausgefuehrt ?

    IMHO holt sich das dlopen zur laufzeit ned die pfade aus der env variable, sondern bekommt irgendwo nen hash, damit findets auch schneller die libs. Den hash erzeugst mit ldconfig ....

    also mal fix vor programmstart die env variable anpassen und voiala, ploetzlich laden die programme alle ne andere version der .so geht so nicht, was auch sinn macht, weils nen ziemliches sicherheitsrisiko waer (programme mit suicid flag nutzen ja auch .so 's und die env variablen kann jeder fuer seine shell ueberschreiben ..... )

    Ciao ...

  9. #9
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von ufosworld Beitrag anzeigen
    nee hab keine root rechte...und auch keine change welche zu bekommen...
    Das war zu Absicherung gefragt, als root geht LD_LIBRARY_PATH aus Sicherheitsgründen nämlich nicht.

    p.s. nen Neustart benötigt man aber net nicht oder... also nacht setzen der Library... (weil soweit ich weiss löscht der das wieder... also das gesetzte Verzeichniss.. also bei Neustart des Systems)
    Nein. Wie gesagt hat dein Beispiel Programm bei mir einwandfrei funktioniert, ich hab extra die Bibliothek in ein anderes Verzeichnis verschoben um sicher zu gehen.

    Da scheint irgendwas faul zu sein, die Frage ist nur was.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  10. #10
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von RHBaum Beitrag anzeigen
    ldconfig hasst aber ausgefuehrt ?

    IMHO holt sich das dlopen zur laufzeit ned die pfade aus der env variable, sondern bekommt irgendwo nen hash, damit findets auch schneller die libs. Den hash erzeugst mit ldconfig ....
    LD_LIBRARY_PATH erweitert den Lookup zur Laufzeit, d.h. dort wird vor den Verzeichnissen gesucht, die der Loader sonst konfiguriert hat.
    ldconfig muß man nur aussführen, wenn man die Konfigurationsdatei in /etc geändert hat.

    also mal fix vor programmstart die env variable anpassen und voiala, ploetzlich laden die programme alle ne andere version der .so geht so nicht, was auch sinn macht, weils nen ziemliches sicherheitsrisiko waer (programme mit suicid flag nutzen ja auch .so 's und die env variablen kann jeder fuer seine shell ueberschreiben ..... )
    Darum geht es auch für root nicht. Für normale User schon (von Spezialsetups mit SELinux oder so abgesehen).

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  11. #11
    Registrierter Benutzer
    Registriert seit
    11.04.2007
    Beiträge
    54

    Thumbs up

    Ok, glaub ich weiss wieso das nicht geht..

    ich mach das setenv LD_LIBRARY_PATH in Console 1

    dann starte ich das Programm aus KDevelop heraus... dieser macht ja wieder eine neue Console auf... d.h. in dieser ist der LD_LIBRARY PATH nicht gesetzt.

    dasselbe gilt für das Konsolen Fenster in Kdevelop...

    d.h. ich müsste direkt bevor er das Programm startet in der Console, in dem er es dann ausführt

    setenv LD_LIBRARY_PATH /blabla

    ablaufen lassen...

    => ich müsste das irgendwo in KDEVELOP bei Parametern für das Consolenfenster das er da mitgibt einfügen... nur WO????

    wenn ich nämlich in der Console, in der ich setenv mach, gleich dannach das Programm starte... funktioniert es auch... d.h. mit "triangle.so" und ohne links im Programm-Verzeichniss....

    zu ldconfig...

    wenn ich ldconfig aufrufe dann kommt nur Befehl nicht gefunden...

    man ldconfig zeigt aber das an was ihr mir erklärt habt...
    leider liegt ldconfig im Verzeichniss /sbin und da hab ich als normaler DAU-User keinen Zugriff drauf... nicht mal lesend....


    aber das ist ja hinfällig, sobald ihr mr sagen könnt wo ich das setenv zeugs in KDevelop einfügen kann...

    ansonsten bleibt mir nur die wahl das Tool in Kdevelop zu entwickeln, aber dann in der Console zu testen...

    grüsse UFO

  12. #12
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von ufosworld Beitrag anzeigen
    Ok, glaub ich weiss wieso das nicht geht..

    ich mach das setenv LD_LIBRARY_PATH in Console 1

    dann starte ich das Programm aus KDevelop heraus... dieser macht ja wieder eine neue Console auf... d.h. in dieser ist der LD_LIBRARY PATH nicht gesetzt.

    dasselbe gilt für das Konsolen Fenster in Kdevelop...
    Klar, es heißt ja auch Umgebungsvariable, d.h. das aktuelle Environment eines Prozesses wird geändert (in diesem Fall der Shell).
    Kindprozesse erben das Environment, d.h. Prozesse die aus der Shell gestartet werden hab es auch gesetzt.
    Ein Prozess kann nicht in das Environment eines anderen eingreifen, daher wirkt sich das nicht auch in ein andere aus.

    aber das ist ja hinfällig, sobald ihr mr sagen könnt wo ich das setenv zeugs in KDevelop einfügen kann...
    Keine Ahnung, vielleicht dort wo man auch die Aufrufparameter des Programms angeben kann, mit denen es bei "Run" ausgeführt wird.

    Ansonsten kannst du die Variable setzen und dann KDevelop in diesem Environment starten, siehe oben.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

  13. #13
    Registrierter Benutzer
    Registriert seit
    11.04.2007
    Beiträge
    54
    Zitat Zitat von anda_skoa Beitrag anzeigen
    Ansonsten kannst du die Variable setzen und dann KDevelop in diesem Environment starten, siehe oben.
    ja das dachte ich mir dann auch... also nicht mehr über K und dann Kdevelop

    sondern in der Console nachdem ich gesetzt habe Kdevelop starten...

    alles klar... denke dann hat sich das erledigt...

    danke für die Hilfe

    ufo :-D

  14. #14
    Registrierter Benutzer
    Registriert seit
    18.03.2005
    Beiträge
    211
    Darum geht es auch für root nicht. Für normale User schon (von Spezialsetups mit SELinux oder so abgesehen).
    DU meinst fuer alle die euid auf 0 haben schaut dlopen nicht auf den LD_LIBRARY_PATH ? Das wuerde auch Sinn machen.
    Meine Linux Kentnisse liegen scho etwas zurueck, warn mal mit Suse 7.3 aktuell, da kann ich mich nicht an sowas erinnern ....

    ja das dachte ich mir dann auch... also nicht mehr über K und dann Kdevelop
    Solche umgebungsvariablen sind doch dafuer da, um sein programmverhalten zu steuern. Wenn dein Binary mal wo laufen soll, brauchst du da doch auch den wert in der LD_LIBRARY_PATH, ohne das KDevelop gestartet ist.
    Denke mal der passendere Ort waere deine private .profile dann dafuer. Damit haette es deine loginshell und damit alle programme die du zu starten vermagst.

    Ciao ....

  15. #15
    Administrator Avatar von anda_skoa
    Registriert seit
    17.11.2001
    Ort
    Graz, Österreich
    Beiträge
    5.477
    Zitat Zitat von RHBaum Beitrag anzeigen
    Solche umgebungsvariablen sind doch dafuer da, um sein programmverhalten zu steuern. Wenn dein Binary mal wo laufen soll, brauchst du da doch auch den wert in der LD_LIBRARY_PATH, ohne das KDevelop gestartet ist.
    Je nach Art der Installation könnten die Module ja in einem der ld Suchpfade installiert sein, dann würde das wegfallen. Oder das Programm wird immer über ein Wrapperscript gestartet, das die entsprechenden Sachen setzt.

    Ciao,
    _
    Qt/KDE Entwickler
    Debian Benutzer

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •