Domanda

duplicato della seguente domanda: C funzione conflitto


Ciao, nel mio progetto attuale devo usare qualche tipo di interfaccia lib. I nomi delle funzioni sono date da questa interfaccia, ciò che questo funzioni fanno è sviluppatori scelta. Per quanto posso dire un progetto deve utilizzare queste funzioni, e quando si tratta di compilazione si sceglie il lib e con essa la funzionalità. Quello che cerco di fare è quello di utilizzare un lib esistente e la mia lib allo stesso tempo, avvolgendo l'altro e lo chiamano nelle funzioni mein:

otherlib:

int function1 (int a) {
// do something
}

mylib:

int function1 (int a) {
//my code here
    otherlib::function1(a);
}

Il problema è che non ho accesso all'altra lib e l'altra lib non ha spazi dei nomi. Ho già provato

namespace old {
    #include "otherlib.h"
}

e quindi chiamare la vecchia funzione dal vecchio :: funzione1 nella mia funzione. Questo funziona finchè è solo file di intestazione. Le esportazioni lib è simbolo nello spazio globale. Anche qualcosa di simile

namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

non ha funzionato. Ultimo ma non meno ho provato ifdefs e definisce suggerito qui

, ma non ero riuscito.

Tutte le idee su come risolvere questo problema? Grazie in anticipo.

EDIT:. Io non ho accesso al vecchio lib né il progetto di entrambe le librerie sono utilizzati

EDIT2: almeno il vecchio lib è uno statico

È stato utile?

Soluzione

I namespace in C risolti usando nomi di libreria prefissi come:

libfoo -> foo_function1
libbar -> bar_function1

Questi prefissi sono spazi dei nomi attuali. quindi se si scrive libbar

int bar_function1(int a) {
     function1(a);
}

Questo è il modo per risolvere i problemi.

C ha spazi dei nomi --- hanno appena chiamato prefissi;)

Un'altra opzione è quella di fare vari trucchi sporchi con caricamento dinamico di librerie come:

h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")

h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")

Altri suggerimenti

Sembra come se l'altro è lib C e il codice è C ++. È possibile eseguire in un problema storpiatura (compilatori C ++ mangle i simboli - aggiunge roba in più nel nome del simbolo non differenziarsi sovraccarichi e simili)

.

Se la libreria è puro C si può provare:

extern "C" { // disable mangling of symbol names in the block
#include "otherlib.h"
}

namespace new_lib { // new is a reserved word
   int function1( int a ) {
      ::function1(a);
   }
}

Non ho provato. Considera anche fornendo i messaggi di errore che si stanno ottenendo.

Un'altra opzione sarebbe (se la libreria è dinamico) caricare dinamicamente la lib e chiamando la funzione. In Linux (non so su Windows) è possibile utilizzare dlopen per aprire la libreria, dlsym per ottenere il simbolo e lo chiamano:

// off the top of my head, not tried:
int function1( int a )
{
   int (*f)(int); // define the function pointer
   void * handle = dlopen( "library.so" );
   f = dlsym( handle, "function1" );
   f( a ); // calls function1(a) in the dynamic library
}

In questo caso, in quanto non si collega alla libreria non sarà possibile ottenere un conflitto simbolo, ma poi di nuovo, è valida solo per le librerie dinamiche ed è abbastanza ingombrante per l'uso regolare.

Aggiorna

Se gli utenti non utilizzano 'otherlib' direttamente (non includeranno intestazioni) e saranno solo C ++, quindi il primo approccio potrebbe essere possibile (anche se orribile a leggere):

// newlib.h
namespace hideout {
   int f( int a );
}
using namespace hideout; // usually I would not put this on the header

// newlib.cpp
extern "C" { // if otherlib is C, else remove this line
#include "otherlib.h"
}
namespace hideout {
   int f( int a ) { return ::f( a*2 ); }
}

// main.cpp
#include "newlib.h"
int main()
{
   std::cout << f( 5 ) << std::endl;
}

Come funziona? Il codice utente vedrà solo una dichiarazione di function1 (nell'esempio f ()) in quanto non sono compresi otherlib.h . All'interno della vostra unità di compilazione si vedono le due dichiarazioni, ma a distinguere attraverso l'uso dello spazio dei nomi. L'istruzione using nell'intestazione non si preoccupa voi come si sono completamente da qualifica nella tua cpp. L'utente main.cpp include solo l'intestazione, in modo che il compilatore vede solo nascondiglio :: f , e vedrà ovunque a causa della istruzione using. Il linker non avrà alcun problema in quanto il simbolo ++ C è storpiato identificare il vero namespace:

// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1

Se il codice utente comprenderà sia l'intestazione e otherlib.h , allora dovrà qualificare quale funzione si vuole chiamare.

Se sei veramente disperata, si potrebbe scrivere una libreria wrapper che utilizza gli spazi dei nomi o prefissi o permette per il trucco dlsym. Questa libreria involucro dovrebbe essere dinamicamente collegati (per evitare i conflitti di simboli). La libreria dinamica potrebbe quindi avere tranquillamente la vecchia libreria statica incorporato in esso. Basta fare in modo di non esportare i simboli dalla libreria statica al momento della libreria wrapper dinamica.

Non si può risolvere questo in fase di collegamento, quindi è necessario per risolvere il problema in fase di esecuzione tramite librerie dinamiche. Il simbolo per queste funzioni è essenzialmente cotto una volta la biblioteca è stata generata. Se due librerie esportano lo stesso simbolo, non possono entrambi essere collegati con staticamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top