Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » GNU/Linux » Shared Objects in C++

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
24.04.2003, 15:12 Uhr
wiZart



Hi,

ich habe ein Problem bei der Erstellung eines Shared Objects, welches C++ Code enthaelt.
Schon herausgefunden habe ich, dass ich mit 'extern "C"' das C++ Name Mangling deaktivieren kann, so dass ich meine exportierte Funktion tadellos mit dlsym() laden kann.
Jedoch wird weder der Constructor noch der Destructor des Moduls aufgerufen.
Momentan ist dies nicht so wichtig, da ich das z.Z. nicht brauche, aber ich koennte mir vorstellen, dass es evtl in zukuenftigen Erweiterungen sinnvoll waere, die Moeglichkeit, solche Funktionen zu nutzen, zu haben.
Was mich jedoch hauptsaechlich stoert ist die Tatsache, dass ich einen Segmentation Fault vorgesetzt bekomme, wenn ich eine Instanz einer im Shared Object implementierten Klasse erstellen moechte.
Deren Constructor ist leer und eigentlich sollte da nicht mehr passieren, als dass "new" Speicher anlegt.
Hier ein kleiner Code-Teil:

-------------------
#include <stdio.h>
#include <glib.h>
#include <../../../include/interfaces.h>

class CTestModule : public IModule
{
public:
virtual CTestModule(void) : m_uRefCount(1) { /* steht nix drinnen */ } ;
virtual guint32 AddRef(void) { return ++m_uRefCount; };
virtual guint32 Release(void) { if (--m_uRefCount == 0) { delete this; return 0; }; return m_uRefCount; };
/* schnipp schnipp */
private:
virtual ~CTestModule(void) {};
long m_uRefCount;
};

extern "C"
{

guint32 GetModules( IModule ***_pppList )
{
IModule **ppList = NULL;
*ppList = new CTestModule(); // <-- Hier verabschiedet er sich
*_pppList = ppList;
((IModule*)(*ppList))->Release();
return 1;
};

// die naechsten beiden werden nicht aufgerufen
void __attribute__ ((constructor)) test_init()
{
printf("Initializing test module\n");
fflush(NULL);
};

void __attribute__ ((destructor)) test_fini()
{
printf("Unloading test module\n");
fflush(NULL);
};

}

---------

Waere toll, wenn mir jemand weiterhelfen koennte.
Danke und Gruesse
Marcus
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
24.04.2003, 15:32 Uhr
wiZart



Ups,

ich habe gerade doch noch einige Sachen gefunden, die so nicht ganz richtig waren.
Der Konstruktor ist nicht virtuell und die GetModules() Routine war aus einer alten Programm-Version.
Die neue Version funktioniert naemlich schon. Manchmal sieht man den Wald vor lauter Baeumen nicht mehr, hehe.
Bliebe nur noch das Problem, dass die init und exit Funktionen nicht von dlopen() und dlcose() aufgerufen werden...

Gruesse
Marcus

Dieser Post wurde am 24.04.2003 um 15:39 Uhr von wiZart editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
24.04.2003, 15:57 Uhr
virtual
Sexiest Bit alive
(Operator)


Es gibt ja auch keine virtuellen ctoren
Die "init Routine" muß _init, die "exit Routine" muß _fini heißen, sonst wird sich nichgt gefunden!
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
25.04.2003, 09:07 Uhr
~wiZart
Gast


Auf meiner Suche im Netz habe ich gefunden, dass _init und _fini wohl veraltet sind und man stattdessen die __attribute__ Befehle benutzen solle. Leider geht es auch nicht, wenn ich die Funktionen entsprechend umbenenne.

Gruesse
Marcus
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
25.04.2003, 10:42 Uhr
virtual
Sexiest Bit alive
(Operator)


Man muß sich offenbar ein wenig auf die Hinterbeine Stellen. So hat es vom Prinzip by mir geklappt:

Das hier ist meine Share Lib:

C++:
/* myso.c */
#include <stdio.h>

void func()
{
    FILE* log  = fopen("myso.log", "a");
    if (NULL != log) fprintf(log, "func called\n");
    fclose(log);
}

void [b]my_init[/b]()
{
    FILE* log  = fopen("myso.log", "a");
    if (NULL != log) fprintf(log, "_init called\n");
    fclose(log);
}

void [b]my_fini[/b]()
{
    FILE* log  = fopen("myso.log", "a");
    if (NULL != log) fprintf(log, "_fini called\n");
    fclose(log);
}



Nun muß ich dem Linker nur noch mitteilen, daß my_init und my_fini die Routinen sind, die die Rolle von _init und _fini übernehmen sollen:

C++:
# makefile
libmyso.so : myso.o
    gcc -fpic -shared [b]-Xlinker -init -Xlinker my_init -Xlinker -fini -Xlinker my_fini[/b] -o libmyso.so myso.o

myso.o : myso.c
    gcc -fpic -shared -c -o myso.o myso.c



P.S.: Nachgeprüft mit dieem Programm:

C++:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main(
    int argc,
    char** argv)
{
    const char* prgname;
    const char* libname;
    const char* symbolname;
    void* libhandle;
    void* symbolhandle;
    int mode = RTLD_LAZY;
    int ret;
    /*
     * Determine invokation name
     */

    prgname = argv[0] + strlen(argv[0]);
    while (prgname>argv[0] && prgname[-1]!='/') prgname--;

    /*
     * Check arguments
     */

    argv++; argc--;
    while (argc)
    {
        if (strcmp(*argv, "--")==0)
        {
            argv++; argc--;
            break;
        }else if (**argv != '-')
        {
            break;
        }else
        {
            if (strcmp(*argv, "-l") == 0 ||
                strcmp(*argv, "--lazy") == 0)
            {
                mode = RTLD_LAZY;
                argv++; argc--;
            }else if (strcmp(*argv, "-n") == 0 ||
                      strcmp(*argv, "--now") == 0)
            {
                mode = RTLD_NOW;
                argv++; argc--;
            }else
            {
                fprintf(stderr, "*** ERROR: %s: unknown option %s\n"
                                "usage: %s [-l|-n] library symbol\n",
                                prgname, *argv, prgname);
                exit(EXIT_FAILURE);
            }
        }
    }
    if (argc != 2)
    {
        fprintf(stderr, "*** ERROR: %s: missing arguments\n"
                        "usage: %s [-l|-n] library symbol\n",
                        prgname, prgname);
        exit(EXIT_FAILURE);
    }
    libname = argv[0];
    symbolname = argv[1];

    /*
     * Open the library
     */

    libhandle = dlopen(libname, mode);
    printf("dlopen(%s, %s) = %p\n",
           libname,
           mode==RTLD_LAZY? "RTLD_LAZY":"RTLD_NOW",
           libhandle);
    if (libhandle == NULL)
    {
        fprintf(stderr, "*** ERROR: %s: dlopen failed: %s\n",
                        prgname,
                        dlerror());
        exit(EXIT_FAILURE);
    }

    /*
     * Get the symbol
     */

    symbolhandle = dlsym(libhandle, symbolname);
    printf("dlsym(%p, %s) = %p\n",
           libhandle,
           symbolname,
           symbolhandle);
    if (symbolhandle == NULL)
    {
        fprintf(stderr, "*** ERROR: %s: dlsym failed: %s\n",
                        prgname,
                        dlerror());
        dlclose(libhandle);
        exit(EXIT_FAILURE);
    }

    /*
     * close the library
     */

    ret = dlclose(libhandle);
    printf("dlclose(%p) = %d\n",
           libhandle,
           ret);
    if (ret != 0)
    {
        fprintf(stderr, "*** ERROR: %s: dlclose failed: %s\n",
                        prgname,
                        dlerror());
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)

Dieser Post wurde am 25.04.2003 um 10:44 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
25.04.2003, 13:44 Uhr
~0xdeadbeef
Gast


Ich würd ganz generell mal nen Blick hier drauf werfen: www.tldp.org/HOWTO/Program-Library-HOWTO/
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
25.04.2003, 13:46 Uhr
~0xdeadbeef
Gast


Und im speziellen noch mal hier drauf: http://tldp.org/HOWTO/mini/C++-dlopen
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
25.04.2003, 14:09 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich kann nicht behaupten, daß die in den Links beschriebenen Vorgehensweisen funktionieren würden. Wenn ich mein Beispiel wie folgt umändere:

C++:
/* myso.c */
#include <stdio.h>

void func()
{
    FILE* log  = fopen("myso.log", "a");
    if (NULL != log) fprintf(log, "func called\n");
    fclose(log);
}

void __attribute__ ((constructor)) my_init()
{
    FILE* log  = fopen("myso.log", "a");
    if (NULL != log) fprintf(log, "_init called\n");
    fclose(log);
}

void __attribute__ ((destructor)) my_fini()
{
    FILE* log  = fopen("myso.log", "a");
    if (NULL != log) fprintf(log, "_fini called\n");
    fclose(log);
}



C++:
#Makefile
libmyso.so : myso.o
    gcc -fpic -shared -o libmyso.so myso.o

myso.o : myso.c
    gcc -fpic -shared -c -o myso.o myso.c


Dann klappt das nicht, genau wie bei wiZart. Da vertraue ich schon lieber meiner Lösung, die tut es wenigstens.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
25.04.2003, 15:31 Uhr
virtual
Sexiest Bit alive
(Operator)


Ich nehms zurück: Beefies Ansatz aus dem HOWTO tut doch (man muß nur die eigenen Logfiles finden!) - Dann ist der Ansatz von Beefy wahrscheinlich sogar dem mit den Linkeroptionen deutlich vorzuziehen. Sorry für den Fehler
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ GNU/Linux ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: