Caricamento librerie dinamiche

di
Anonimizzato4877
il
1 risposte

Caricamento librerie dinamiche

Salve,
è tutto il giorno che sto combattendo contro il C.
Per un mio progettino devo fare un modesto sistema a plugin. L'ho pensata in questo modo:
1 - Una qualche interfaccia che definisca le chiamate del plugin.
2 - Svariate librerie dinamiche (i plugin per l'appunto) che implementano l'interfaccia.
Dovrebbe essere semplice, invece...
Il codice di base è il seguente:
Il file plugin_1.cpp che implementa il metodo void a(void)
#include <stdio.h>

void a() {
	printf("a - ciao");
}
[/b]
Viene compilato con:
g++ -I. -ldl -Wl,-soname,libplugin_1.so -fPIC -shared -o libplugin_1.so plugin_1.cpp

Il file main.cpp

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

#define PATH_LIBRARY "/home/law/Documents/uni/2_anno/2_sem/cg_project/netbeans/libdisplay3D/bin"
#define NAME "plugin_1"

typedef void (*simpleCall_prototype) (void);
simpleCall_prototype simpleCall;

static void * libPointer;

void * loadLibrary(char * name) {
           void * libPointer;
           char * error;
           char * dynlibName=new char[256];
           snprintf(dynlibName,256,"%s/lib%s.so",PATH_LIBRARY,name);

          fprintf(stderr,"loading %s\n",dynlibName);
           libPointer = dlopen(dynlibName,RTLD_LAZY);
           
          fprintf(stderr,"bin_loadBinLibrary: loaded\n");             
          fprintf(stderr,"bin_loadBinLibrary: looking for error\n");      
          if ( (error=dlerror()) !=NULL || !libPointer) {
               fprintf(stderr,"bin_loadBinLibrary: %s", error);    
               
               return NULL;
          }
          return libPointer;
}
        
int  loadSymbols() {
    char * error;
    int retval;
    simpleCall=(simpleCall_prototype) dlsym(libPointer, "a");
    if ( (error=dlerror()) !=NULL || !simpleCall) {
	fprintf(stderr,"loadSymbols: %s\n",error);
	retval=0;
    } else {
        fprintf(stderr,"loadSymbols: a()  LOADED\n");  
	retval=1;
    }
    return retval;
}
          

int main(int argc, char** argv) {
    void * libPointer=loadLibrary(NAME);
    if (libPointer) {
        if (loadSymbols()) { 
		fprintf(stderr,"main: symbol loaded\n");
		simpleCall();
	}
	else {
		fprintf(stderr,"main: can't load symbol\n");
	}
    } else {
        fprintf(stderr,"main: can't load %s\n library",NAME);
    }
    return (EXIT_SUCCESS);
}
[/b]
compilato con:
g++ -I. -ldl -L./ -rdynamic -Wall -o main main.cpp

L'output del programma:
law@alisss:~/Documents/uni/2_anno/2_sem/cg_project/netbeans/libdisplay3D/bin$ ./main
loading /home/law/Documents/uni/2_anno/2_sem/cg_project/netbeans/libdisplay3D/bin/libplugin_1.so
bin_loadBinLibrary: loaded
bin_loadBinLibrary: looking for error
loadSymbols: ./main: undefined symbol: a
main: can't load symbol

Ma il simbolo a in realtà è presente come da output di nm:
law@alisss:~/Documents/uni/2_anno/2_sem/cg_project/netbeans/libdisplay3D/bin$ nm libplugin_1.so
000016d8 d DW.ref.__gxx_personality_v0
000015bc a _DYNAMIC
000016b8 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
000004bc T _Z1av
000015ac d __CTOR_END__
000015a8 d __CTOR_LIST__
000015b4 d __DTOR_END__
000015b0 d __DTOR_LIST__
000005a4 r __FRAME_END__
000015b8 d __JCR_END__
000015b8 d __JCR_LIST__
000016dc A __bss_start
w __cxa_finalize@@GLIBC_2.1.3
000004f0 t __do_global_ctors_aux
00000420 t __do_global_dtors_aux
000016d0 d __dso_handle
w __gmon_start__
U __gxx_personality_v0@@CXXABI_1.3
000004b7 t __i686.get_pc_thunk.bx
000016dc A _edata
000016e0 A _end
00000524 T _fini
000003ac T _init
000016dc b completed.5982
00000480 t frame_dummy
000016d4 d p.5980
U printf@@GLIBC_2.0

Non so proprio dove sbattere la testa.
Suggerimenti, consigli, alternative sono molto apprezzate
Ringrazio anticipatamente,
Lawrence

1 Risposte

  • Re: Caricamento librerie dinamiche

    Beh, smanettando ancora un pò ne sono venuto fuori...
    Purtroppo per questo progetto ho utilizzato netbeans, che va molto bene per lavori su java e in generale per applicazioni distribuite tipo webservices ecc. ma fà letteralmente cagare per il C/C++. In ogni caso ho impostato il progetto come una libreria C++ anche se il tutto è scritto in puro C. Questo non sarebbe un problema se in effetti il compilatore usato sarebbe il cpp tradizionale. Purtroppo il compilatore di default è il g++, la versione C++ del GNU cpp... Quindi un compilatore che risolve lo spazio dei nomi, e per le chiamate esterne da libreria bisogna aggiungere:
    extern "C" void funzione(void) { 
        //codice....
    }
    extern "C" e passa la paura
    In effetti nelle librerie dinamiche andrebbe sempre messo..
Devi accedere o registrarti per scrivere nel forum
1 risposte