2009-02-21 10 views
7

Ho creato una DLL C++ che vorrei chiamare dal codice C#. Sono in grado di chiamare una funzione, ma l'altra genera un'eccezione quando il codice C# tenta di caricare la DLL.Esportazione di funzioni da C++ dll a C# P/Invoke

L'intestazione assomiglia a questo: (? Che cosa foo = foo dire nel campo del nome)

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

Questo produce una DLL con tavolo esportazioni po 'confusa:

File Type: DLL 

Section contains the following exports for PPPManager.dll 

00000000 characteristics 
499F44F0 time date stamp Fri Feb 20 16:04:00 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000078E4 Install = Install 
     2 1 000079DC PPPConnect = PPPConnect 

mio P/invocare dichiarazioni appaiono così:

[DllImport("PPPManager.dll")] 
private static extern bool Install(); 

[DllImport("PPPManager.dll")] 
private static extern bool PPPConnect(); 

La chiamata a installare i rendimenti senza alcuna eccezione, ma quando chiamo PPPConnec t, Ottengo un MissingMethodException - "Impossibile trovare un punto di ingresso 'PPPConnect' in un PPPManager.dll 'PInvoke DLL."

Ho provato a rimuovere le direttive extern e declspec dalla dichiarazione della funzione Installa, in modo che PPPConnect sia l'unica funzione esportata e questo non mi consente di chiamare PPPConnect.

Ho anche provato a eseguire DllImport per ordinale; questo dà lo stesso risultato della chiamata per nome - Installa i ritorni, ma PPPConnect lancia l'eccezione "Impossibile trovare un punto di ingresso '# 2' ...".

Il registro di interoperabilità dà:

[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::Install(); 
BOOLEAN (I1_WINBOOL_VAL) Install(); 

JIT ERROR FOR PINVOKE METHOD (Managed -> Native): 
[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::PPPConnect(); 
BOOLEAN (I1_WINBOOL_VAL) PPPConnect(); 

Questo è ben al di fuori la mia area di competenza, quindi qualsiasi suggerimento o pensieri sarebbe il benvenuto.

Grazie, Paul

edit: Si scopre che questo codice funziona; il problema era che l'ultima DLL non veniva propagata al dispositivo. D'oh!

+0

Non ho mai sentito parlare di questo registro di interoperabilità - come si fa a attivare/Vedi quello? – Charlie

+0

http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx Ho appena iniziato a usarlo per provare a eseguire il debug di questo problema, ma sembra che mi avrebbe salvato un sacco di tempo di debug di MissingMethodExceptions. – Symmetric

risposta

8

Si sta utilizzando un file .def nel progetto dll per esportare tali funzioni? Se è così, rimuovilo e riprova. Questa è solo un'ipotesi perché sembra che le tue esportazioni non siano quello che dovrebbero essere quando esegui un declspec (dllexports) externale.

ho provato questo con un semplice dll C++ utilizzando

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

e una semplice app C# utilizzando le dichiarazioni di PInvoke e ha funzionato bene.

Quando ho fatto un dumpbin/export sul dll che ho visto:

dump del file di PPPManager.dll

File Type: DLL

sezione contiene i seguenti esportazioni PPPManager.dll

00000000 characteristics 
499F6C2D time date stamp Fri Feb 20 20:51:25 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000110CD Install = @ILT+200(_Install) 
     2 1 00011069 PPPConnect = @ILT+100(_PPPConnect) 

Si noti che i nomi esportati sono diversi nel mio caso.

+0

Alla fine si scopre che non stavo copiando l'ultima DLL, a causa del mio fraintendimento del comando "Aggiungi file da proiettare" in VS. La tua idea di provare una dll ridotta era il seme di cui avevo bisogno per andare a capirlo. Grazie! – Symmetric

+0

Ottimo! Sono contento di poterti aiutare. –

0

Ottime informazioni, ma come dici tu, tutto è in ordine qui. Prova a installare Debugging Tools per Windows ed esegui:

per ottenere un dump migliore della tabella dei simboli; si tratta di un colpo cieco pure, ma si potrebbe anche provare:

extern "C" 
{ 
    __declspec(dllexport) BOOL Install(); 
    __declspec(dllexport) BOOL PPPConnect(); 
}; 

nel caso in cui il __declspec sta facendo qualcosa di strano.

1

Potrebbe essere qualcosa di semplice come il PPPConnect errore in un modo che viene interpretato erroneamente dal sistema operativo. Prova ad implementare sia Install e PPPConnect come non-ops (basta farli restituire TRUE senza fare altro) e vedere se l'errore persiste. In tal caso, prova a scambiare l'ordine in cui vengono esportati (sempre come non operativi) e vedere se il problema è legato all'ordine (improbabile) oa qualcos'altro.

È inoltre possibile utilizzare lo strumento grafico depends per confermare l'aspetto della tabella delle esportazioni della DLL, ma dubito che il problema provenga da questi ambienti.

+0

Queste sono buone idee per isolare il vero problema. Potresti anche provare ad aggiungere una terza funzione e vedere cosa succede con quella. – Charlie

1

In base alla descrizione, Install e PPPConnect differiscono solo nei nomi. Immagino che tu usi semplicemente la vecchia versione .dll con l'applicazione C#. Uno senza PPPConnect definito.

Le dichiarazioni sembrano corrette (per quanto posso giudicare senza fonti).

0

uso Dependency Walker e aprire la DLL per verificare quali metodi sono disponibili