2015-07-08 14 views
5

Sto provando a utilizzare due librerie di algebra lineare grandi e complesse che definiscono molte delle stesse funzioni. Non posso riscrivere (legalmente in un caso, ma tecnicamente in entrambi) entrambi. Chiamiamoli "speciali" e "normali" perché io chiamo solo un paio di funzioni da speciali. Per funzioni definite in normal.h e solo in alcuni casi da chiamare costantemente, ho fatto qualcosa di simile:Modello di collegamento predefinito in gcc 4.4 e gcc> 4.4

namespace special_space 
{ 
#include "special.h" // Defines foo() 
} 

#include "normal.h" // Defines foo() 

int main() { 
    foo();    // Calls foo() defined in normal.h 
    special_space::foo(); // Calls foo() defined in special.h 
} 

Con g ++ - 4.4, che era il predefinita in cui stavo sviluppando questo, il codice viene compilato e collegamenti senza avvertenze, e si esegue come mi aspetto e come voglio. Questo sembra essere coerente tra piattaforme, vari ambienti Linux, Unix e BSD. Ma! se compilo con g ++> 4.4, ricevo avvertimenti circa multipla foo() definizioni:

nel file di special.h :: linea: col: avvertimento: dichiarazione di 'vuoto special_space :: foo()' con il linguaggio C collegamento [abilitato per impostazione predefinita]

L'eseguibile risultante quindi segfaults alla chiamata a special_space::foo(). I/think/che specificando extern "C++" nelle definizioni trovate in special.h potrebbe risolvere questo problema, ma non sono autorizzato a cambiare special.h. Quindi cosa dovrei fare? Più precisamente:

1) È sicuro usare g ++ - 4.4? Se è così - cosa è cambiato nelle versioni successive e perché?

2) Se specificando il modello di collegamento C++ si risolverebbe davvero questo, c'è un modo per dire ld di usarlo di default?

3) Se nessuno di questi - esiste un altro modo per chiamare funzioni da librerie che definiscono funzioni con lo stesso nome?

+2

Entrambe le funzioni hanno il collegamento C in origine? Se sì: [Le funzioni C disattivano il nome mangling] (http://stackoverflow.com/questions/9685994/c-extern-c-functions-inside-a-namespace) – WorldSEnder

+1

Prova a includere entrambi in " #ifdef __cplusplus extern "C" { #endif #include normal.h #ifdef __cplusplus } #endif' – rost0031

+1

Se non è possibile modificare le librerie allora che già hanno un particolare modello di collegamento, e non si può cambiare la situazione. – nneonneo

risposta

1

Così come ho postato in un commento, avvolgere le intestazioni include con

#ifdef __cplusplus 
extern "C" { 
#endif 

#include normal.h 

#ifdef __cplusplus 
} 
#endif 

farlo con entrambe le intestazioni.

Fondamentalmente, dal momento che si collegano le librerie c da C++, che indica il mangling (questo è ciò che consente l'overloading), le chiamate ai simboli nel proprio c lib venivano manomesse dal linker. Il #ifdef __cplusplus dice al linker di non manipolare i nomi per quei simboli di funzioni specifici.

Idealmente, i creatori della libreria dovrebbero includere questo nelle intestazioni, ma hai detto che non hai il controllo su questo. Ho avuto un problema simile con un po 'di codice generato. Ho dovuto racchiudere tutte le mie intestazioni includendo il codice generato in questo per consentire a C++ di chiamarlo.

Quello che non so, è come mai ha funzionato senza questo. Ho sicuramente dovuto farlo tornare a gcc < 4.4.

+0

Per i nomi dei nomi: le intestazioni problematiche provenivano da GSL (gsl/gsl_linag.h e gsl/gsl_blas.h) e da Intel MKL (mkl.h e mkl_lapacke.h). – gerowam

Problemi correlati