2014-05-24 24 views
8

Ho una domanda relativa all'inserimento di una libreria in un'altra.Come incorporare una libreria C++ in una libreria C?

Ho un codice che è puro C e i miei utenti si affidano a questo, non vogliono dipendere dalle librerie C++. Tuttavia, è nata l'esigenza di incorporare una libreria di terze parti (ICU) nella mia. Nessuna delle funzioni ICU sarebbe stata esportata, sarebbero state utilizzate solo internamente nella mia libreria. Sfortunatamente l'ICU è una libreria C++, sebbene abbia un wrapper C. L'ICU non usa eccezioni, ma usa RTTI (classi base astratte).

La domanda è: come avrei potuto creare la mia libreria statica in modo che

  1. ICU è incorporato nella mia biblioteca (tutti i riferimenti alle funzioni di terapia intensiva sono risolte all'interno della mia biblioteca)
  2. tutti i riferimenti a libstdC++ sono inoltre deliberato e il codice necessario è incorporato nella mia libreria
  3. se un utente non ha nemmeno libstdC++ installato sul proprio sistema funziona perfettamente
  4. se un utente utilizza la mia libreria all'interno di un progetto C++ non ci sono conflitti con whateve r libstdC++ (presumibilmente il sistema libstdC++) che usa.

È possibile? Le piattaforme target sono praticamente tutto: windows (la mia libreria è dinamica) e tutte le versioni unix (linux, solaris, aix, hpux - qui la mia libreria deve essere statica).

gcc-4.5 e versioni successive ha --static-libstdC++, ma per quanto ne so è solo per la creazione di librerie o di eseguibili condivisi e non di librerie statiche.

Grazie per qualsiasi aiuto!

+1

Questo POTREBBE non essere possibile .. Beh in "la mia esperienza" almeno. Una libreria compilata con una versione specifica di libstdC++ non sembra sempre compatibile con un'altra versione. Di solito dà errori di linker. Anche per Visual Studio. Osservo librerie come OpenCV che spedisce build diverse. VC10, VC11, VC12, ecc. (L'ho costruito ieri sera). Quello che facevo era compilare tutto fino ai loro file .o. Quindi esegui 'ar -rcs * .o' dove i file o sarebbero tutte le dipendenze come zlib, libpng, ecc. Non pensare di poterti scappare da libstd anche se ... Mi piacerebbe anche una risposta a questa domanda . – Brandon

+1

dlopen + dlsym potrebbe essere il modo di usare l'ICU da C senza creare dipendenze in fase di compilazione. – ArtemGr

+0

@ArtemGr: ciò andrebbe bene tranne che per una cosa: ho bisogno di distribuire icu lib perché non posso presumere che l'utente ce l'abbia. Ma poi, ovviamente, ho bisogno di compilarlo. E (diciamo che sono su linux) l'ABI C++ per il compilatore che ho sulla mia macchina di compilazione potrebbe non essere compatibile (ad es. Per la risoluzione RTTI) con l'ABI C++ che l'utente ha sulla sua macchina. Quindi, se ho dlopen + dlsym la libreria icu che ho distribuito, potrei incorrere in problemi quando comincio a correre. Ecco perché voglio risolvere e collegare tutto e creare la mia libreria in questo modo. – LaszloLadanyi

risposta

4

La soluzione a questo problema è piuttosto semplice, ma potrebbe non rientrare nei parametri impostati.

Le semplici regole sono:

  1. È possibile collegare dinamicamente una libreria C++ per un chiamante C, ma si deve avvolgere la libreria all'interno di un livello C extern. Si progetta l'API C extern e si implementa utilizzando internals C++, che sono sempre nascosti alla vista. [È anche possibile utilizzare COM o .NET per eseguire questa operazione su Windows.]
  2. È possibile che non sia collegare in modo statico una libreria C++ a un chiamante C. Le librerie sono diverse e le sequenze chiamanti/i simboli del linker sono diverse. [Spesso non si può nemmeno collegare staticamente tra diverse versioni dello stesso compilatore, e quasi mai tra diversi compilatori.]

In altre parole, la soluzione è semplice: utilizzare il collegamento dinamico. Se questa non è la risposta giusta, allora non penso che ce ne sia una.

Solo per rendere le cose interessanti, è anche possibile implementare la propria architettura plug-in. Questo è solo un altro nome per il collegamento dinamico, ma puoi scegliere l'API.


tanto per essere chiari, l'unica opzione praticabile portatile che posso vedere è che si collega ICU all'interno della propria libreria dinamica (DLL o SO). I suoi simboli, le librerie C++, RTTI e le eccezioni rimangono tutti dentro. I tuoi collegamenti di lib statici alla lib dinamica ICU di extern C. Quella è esattamente la quantità di Windows costruita: C++ all'interno di DLL, extern C.

È possibile eseguire il debug attraverso il limite, ma non è possibile esportare le informazioni sul tipo. Se è necessario, è necessario utilizzare un'API diversa, ad esempio .NET o COM.

+0

Sì, è così che funziona il wrapper C ICU, esso avvolge la libreria ICU C++ su un'interfaccia C esterna. E questa è l'interfaccia che voglio usare nel mio Libreria C. In modo che la parte sia chiara.Che cosa non è chiaro se posso legare i simboli della libreria ICU, il suo wrapper C e libstdC++ tutto nel momento in cui creo la mia libreria? Temo che non sia possibile – LaszloLadanyi

+0

se voglio la mia lib static e spero che sia possibile se la mia è condivisa (se lo è, come?). Si noti che l'associazione deve includere tutte le informazioni RTTI, che non è fuori questione in quanto è garantito che ho già tutte le possibili istanze di chiamate e forse posso indicarlo al raccoglitore. D'altro canto ICU non usa eccezioni (finora) quindi non ho bisogno di affrontarlo. – LaszloLadanyi

+0

Non proprio. Vedi modifica. –

0

Non so se questo funzionerà, ma lasciatemi suggerire almeno di provarlo!

L'eccellente LLVM project (origine del compilatore clang) ha molti front-end e back-end per lingue diverse, come C++ e C. E secondo this S.O. question dovrebbe essere possibile per LLVM compilare C++ in C che a sua volta può essere compilato normalmente.

Immagino che questo percorso sia accidentato, ma se funziona, potrebbe risolvere il problema senza la necessità di collegarsi dinamicamente. Tutto dipende da se ICU verrà compilato con LLVM C++.

Se decidi di provarci, facci sapere come stai!

+0

Sono davvero entusiasta di questo commento, ma è un no-go :-(. Ho trovato questo post su https://groups.google.com/forum/#!topic/llvm-dev/Uu72xwp9z2w: Il backend C è stato rimosso in 3.1 (http: // llvm .org/releases/3.1/docs/ReleaseNotes.html): "Principali modifiche e funzionalità rimosse ... Il backend C è stato rimosso. Ha avuto numerosi problemi, al punto di non essere in grado di compilare alcun programma non banale. " – LaszloLadanyi