2012-04-11 19 views
15

Sto cercando di imparare P/Invoke, così ho creato un semplice DLL in C++Impossibile trovare un punto di ingresso al momento della chiamata C++ DLL in C#

KingFucs.h:

namespace KingFuncs 
{ 
    class KingFuncs 
    { 
    public: 
     static __declspec(dllexport) int GiveMeNumber(int i); 
    }; 
} 

KingFuns.cpp :

#include "KingFuncs.h" 
#include <stdexcept> 

using namespace std; 

namespace KingFuncs 
{ 
    int KingFuncs::GiveMeNumber(int i) 
    { 
     return i; 
    } 
} 

quindi non compilare, poi ho copiato questo dll nella mia cartella di debug del WPF, con il codice:

[DllImport("KingFuncDll.dll", EntryPoint = "GiveMeNumber", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] 
     public static extern int GiveMeNumber(
       int i 
      ); 

e chiamandolo a scatto del tasto:

private void Button_Click(object sender, RoutedEventArgs e) 
{ 
    int num = GiveMeNumber(123); 
} 

ma mi dà eccezione:

Impossibile trovare un punto di ingresso denominato 'GiveMeNumber' nella DLL 'KingFuncDll.dll'.

Davvero .... cosa ho fatto di sbagliato ... Ovviamente è in grado di trovare la DLL, altrimenti sarebbe un'altra eccezione. Ma il mio nome del metodo è esattamente lo stesso ... Non riesco a pensare ad altro motivo.

+1

Si prega di vedere la mia domanda qui: http://stackoverflow.com/questions/9849541/writing-c-intestato-per-essere-called-da-c –

+0

Ho risolto la stessa domanda e la descrivo in [questo post] (https://stackoverflow.com/a/45263176/1817569). – Hamid

risposta

31

È necessario utilizzare extern "C" quando si esporta la funzione in modo da sopprimere il nome di manganing del nome C++. E non dovresti nemmeno cercare di invocare i membri di una classe. Usare le funzioni libere invece:

extern "C" { 
    __declspec(dllexport) int GiveMeNumber(int i) 
    { 
     return i; 
    } 
} 

Sul lato gestito l'attributo DllImport è tutto sbagliato. Non utilizzare SetLastError che è solo per le API Win32. Non preoccupatevi di impostare CharSet se non ci sono parametri di testo. Non è necessario per ExactSpelling. E la convenzione di chiamata è presumibilmente Cdecl.

[DllImport("KingFuncDll.dll", CallingConvention=CallingConvention.Cdecl)] 
public static extern int GiveMeNumber(int i); 
+0

Grazie, ha funzionato. Ma non è possibile chiamare una funzione di una classe? (Questa è la mia prima volta che utilizzo extern "C", ho pensato di dover sempre definire la funzione all'interno di una classe in C++) –

+0

Non è necessario definire una funzione all'interno di una classe in C++. Le funzioni C obsolete vanno bene. –

0

Il problema è che si dichiara la ++ "funzione" C all'interno di una classe C++ e dici P/Invoke per usare stdcall.

Provare a dichiarare una funzione C++ al di fuori di una classe ed esportarla come hai fatto tu. Quindi il tuo codice dovrebbe funzionare.

Se davvero si deve avere una funzione C++ all'interno di una classe, dare un'occhiata a CallingConvention.ThisCall. Ma sei responsabile della creazione della tua istanza di classe non gestita e passala come primo parametro della tua chiamata P/Invoke

0

Il nome del punto di ingresso di un file dll è indicato nel file .exp che si trova nella cartella di debug dove altri i file di origine sono presenti. Se dumpbin non funziona, puoi provare questo.

Problemi correlati