2009-02-21 16 views
7

Ich habe eine C++ - DLL, die ich möchte von C# -Code aufrufen. Ich kann eine Funktion aufrufen, aber die andere löst eine Ausnahme aus, wenn der C# -Code versucht, die DLL zu laden.Exportieren von Funktionen von C++ - DLL zu C# P/Invoke

Der Header sieht wie folgt aus: (? Was bedeutet foo = foo im Namensfeld bedeuten)

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

Dieses eine DLL mit etwas verwirrend Exporte Tabelle erzeugt:

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 

My P/Aufrufen Deklarationen sehen wie folgt aus:

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

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

Der Aufruf der Installation wird ohne Ausnahme zurückgegeben, aber wenn ich PPPConnec aufrufen t, bekomme ich eine MissingMethodException - "Kann einen Einstiegspunkt 'PPPConnect' in einer PInvoke DLL 'PPPManager.dll' nicht finden."

Ich habe versucht, entfernen Sie die externen und declspec-Anweisungen von der Funktion Deklaration installieren, so dass PPPConnect ist die einzige Funktion exportiert, und dies lässt mich PPPConnect immer noch nicht aufrufen.

Ich habe auch versucht, die DllImport von Ordnungszahl; Dies führt zu dem gleichen Ergebnis wie das Aufrufen des Namens - Install returns, aber PPPConnect löst die Ausnahme "Kann keinen Einstiegspunkt finden" # 2 '... "aus.

Der Interop-Protokoll gibt:

[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(); 

Dies ist auch außerhalb mein Fachgebiet, so irgendwelche Vorschläge oder Gedanken zu begrüßen wäre.

Danke, Paul

edit: Es stellt sich heraus, dass dieser Code funktioniert; Das Problem bestand darin, dass die neueste DLL nicht auf das Gerät übertragen wurde. Oh!

+0

Ich habe noch nie von diesem Interop-Protokoll gehört - wie kann man aktivieren/das ansehen? – Charlie

+0

http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx Ich habe gerade angefangen, es zu verwenden, um dieses Problem zu debuggen und zu versuchen, aber es scheint, als hätte es mir eine Menge gerettet Zeit Debugging MissingMethodExceptions. – Symmetric

Antwort

8

Verwenden Sie eine .def-Datei in Ihrem DLL-Projekt, um diese Funktionen zu exportieren? Wenn ja, entferne es und versuche es erneut. Dies ist nur eine Vermutung, denn es sieht so aus, als wären Ihre Exporte nicht das, was sie sein sollten, wenn Sie eine externe "C" -deklspec (dllexports) machen.

Ich habe versucht, dies mit einem einfachen C++ dll

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

und einem einfach C# app mit Ihrer PInvoke Erklärung mit und es funktionierte gut.

Wenn ich habe eine dumpbin/exports auf der dll ich sah:

Dump der Datei PPPManager.dll

Dateityp: DLL

Abschnitt folgende Exporte für PPPManager.dll enthält

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) 

Beachten Sie, dass die exportierten Namen in meinem Fall anders sind.

+0

Am Ende stellt sich heraus, dass ich die letzte DLL nicht kopiert habe, weil ich das falsch verstanden habe, was der Befehl "Datei zum Projekt hinzufügen" in VS tut. Ihre Idee, eine abgespeckte DLL auszuprobieren, war der Keim, den ich brauchte, um das herauszufinden. Vielen Dank! – Symmetric

+0

Großartig! Froh, dass ich helfen konnte. –

0

Großartige Informationen, aber wie Sie erwähnen, ist hier alles in Ordnung. Versuchen Sie, die Debugging-Tools für Windows zu installieren und zu starten:

kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*" 

, um einen besseren Speicherauszug der Symboltabelle zu erhalten; es ist ein blinder Schuss als auch, aber man könnte auch versuchen:

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

falls das __declspec seltsam, etwas zu tun ist.

1

Es könnte etwas so einfach sein wie PPPConnect Fehler in einer Weise, die vom Betriebssystem fehlinterpretiert wird. Versuchen Sie, sowohl Install als auch PPPConnect als No-Ops zu implementieren (lassen Sie sie einfach TRUE zurückgeben, ohne etwas anderes zu tun) und sehen Sie, ob der Fehler weiterhin besteht. Wenn dies der Fall ist, versuchen Sie, die Reihenfolge zu ändern, in der sie exportiert werden (immer noch als Nicht-Ops), und sehen Sie, ob das Problem an die Reihenfolge (unwahrscheinlich) oder an etwas anderes gebunden ist.

Sie können auch das grafische Tool depends verwenden, um zu bestätigen, wie die Tabelle der DLL-Exporte aussieht, aber ich bezweifle, dass das Problem von diesen Vierteln kommt.

+0

Dies sind gute Ideen, um das eigentliche Problem zu isolieren. Sie könnten auch versuchen, eine dritte Funktion hinzuzufügen und zu sehen, was mit diesem passiert. – Charlie

1

Gemäß Ihrer Beschreibung unterscheiden sich Install und PPPConnect nur in Namen. Ich denke, Sie verwenden einfach die alte DLL-Version mit Ihrer C# -Anwendung. Eine ohne PPPConnect definiert.

Die Erklärungen sieht richtig aus (soweit ich ohne Quellen beurteilen kann).

0

Verwendung Dependency Walker und Ihre DLL öffnen, um zu überprüfen, welche Methoden

verfügbar sind