2010-06-02 6 views
5

Questa domanda potrebbe sembrare una ripetizione di quelle precedenti. Ho letto una serie di post, ma non completamente chiaro per la mia situazione.Chiama libreria C++ da C#

Ho una libreria C++ che viene creata utilizzando l'IDE di momento. Devo essere in grado di utilizzare questa libreria in un progetto C#.

Qualcuno aveva lavorato a questo progetto prima di essere consegnato a me. Attualmente, ci sono 2 livelli per renderlo possibile. Innanzitutto, un progetto C++ include la libreria completa con un wrapper C++. Questo progetto crea una DLL come output. Questa DLL C++ viene quindi inviata a un progetto C#, che ha chiamate dllimport alla dll C++. Questo progetto C# crea nuovamente una dll. Infine, per utilizzare la libreria nell'applicazione C#, devo includere un riferimento a entrambe le dll.

È questo il modo corretto per farlo funzionare? Stavo pensando che probabilmente ci dovrebbe essere un modo per semplificare il processo.

Qualcuno può aiutarmi con questa domanda?

+0

possibile duplicato di [Come chiamo C++ nativo da C#?] (http://stackoverflow.com/questions/2211867/how-do-i-call-native-c-from-c) – Randolpho

risposta

7

Dato che si sta utilizzando un ++ libreria C, sto assumendo si avvale di C++ semantica come le classi, piuttosto piuttosto che esporre le procedure. Se questo è il caso, il modo in cui ciò viene fatto in genere è tramite una libreria di interoperabilità C++ gestita manualmente creata.

Fondamentalmente, si crea una libreria C++ gestita in Visual Studio, si fa riferimento alla libreria C++ esistente e si crea un wrapper gestito attorno alle classi C++ esistenti. Quindi fai riferimento a questo assembly C++ (gestito) nel tuo progetto C# e includi la libreria C++ originale (non gestita) nell'assembly C# come un file che viene inserito nella directory di build.

Questo è necessario perché non c'è modo di fare riferimento a cose come classi C++ tramite chiamate P/Invoke (DllImport).

Se la libreria di base è solo una serie di funzioni, è possibile farvi riferimento direttamente nel progetto C# tramite le funzioni P/Invoke.

In entrambi i casi, tutte le librerie citate sopra (per la prima, la libreria C++ non gestita, l'assembly C++ gestito e il progetto C#, o, per la seconda, la libreria C++ non gestita e il progetto C#) devono essere inclusi in qualsiasi progetto che li faccia riferimento. Non è possibile collegare staticamente la libreria non gestita all'assembly gestito.

+2

+1, ma vorrei sottolineare che a meno che non stiate usando .NET. 1.1, "managed C++" è ora chiamato "C++/CLI", e ci sono * enormi * differenze tra i due. – Randolpho

+0

Inoltre, penso che tu intenda "non puoi collegare dinamicamente la libreria non gestita". * Il collegamento statico * è l'unico modo per utilizzare la libreria. – Randolpho

+0

Grazie mille ... Come hai detto, la lib non gestita ha classi e interfacce. Stando così le cose, credo di dover avere un wrapper C++ e un wrapper C# per poter usare la lib C++ non gestita nella mia app C#, giusto? Ora il wrapper C++ ha il compito di creare un'istanza delle classi e implementare l'interfaccia, è corretto? Ho un'altra domanda. È il lavoro della lib non gestita per fornire le funzionalità extern "C" e _dllexport? Al momento non funziona, ma posso inserirlo come requisito per il prossimo progetto, quindi voglio solo accertarmene. – Batul

0

È possibile uso:

DllImport

class Example 
{ 
    // Use DllImport to import the Win32 MessageBox function. 
    [DllImport("user32.dll", CharSet = CharSet.Unicode)] 
    public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type); 

    static void Main() 
    { 
     // Call the MessageBox function using platform invoke. 
     MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0); 
    } 
} 
2

Sembra che tu abbia un involucro di troppo ma forse qualcuno sta implementando una sorta di facciata o aggiungendo proprietà o qualcosa del genere. La connessione di base tra gestita e non gestita sarà DllImport di chiamate di funzioni "piatte" - non funzioni membro - o funzioni membro di chiamata codice C++/CLI. Se il wrapper è C++/CLI è più facile scrivere (basta includere l'intestazione per la libreria C++) e più facile da chiamare (il codice C# aggiunge solo un riferimento a .NET e continua normalmente) quindi sarebbe la mia prima scelta se c'è competenza C++ sul progetto.

Sembra che chiunque stia prendendo il controllo stia facendo la cosa più difficile. Se ci sono meno di 20 metodi, suggerirei di ricominciare da capo.

+0

Ricominciare da capo sembrava la soluzione migliore anche per me, ma una volta iniziato, qualunque cosa guardassi, indicavo solo che la soluzione corrente era il modo corretto per farlo. Quello che capisco dal tuo suggerimento è anche quello di avere un wrapper C++ per gestire le classi nella lib C++ non gestita, e quindi usare le chiamate dllImport in C#. Ho ragione? – Batul

+0

Se aggiungi un wrapper C++/CLI, può salvarti da P/Invoke (DllImport.) Fondamentalmente il tuo codice C++/CLI può semplicemente "includere l'intestazione, il link alla lib" per usare il tuo codice nativo. Tutto ciò che è 'public ref class Foo' nel codice C++/CLI può essere chiamato da C# senza alcun meccanismo di interoperabilità - basta aggiungere un riferimento e usarlo. –

+0

Grazie Kate. Da quanto ho letto finora, DllImport richiede una struttura piatta nella lib non gestita, cioè senza classi e interfacce. Ma la mia lib non gestita ha classi e interfacce, quindi vuol dire che non posso usare DllImport? Se è così, quindi creare C++/cli wrapper è l'unico modo per andare? – Batul