2009-02-21 15 views
7

Zbudowałem bibliotekę C++, którą chciałbym wywołać z kodu C#. Jestem w stanie wywołać jedną funkcję, ale druga rzuca wyjątek, gdy kod C# próbuje załadować bibliotekę dll.Eksportowanie funkcji z biblioteki dll C++ do C# P/Invoke

nagłówek wygląda tak: (Co robi foo = foo oznacza w polu nazwy)

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

ta produkuje dll z nieco mylące tabeli eksporcie:

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 

Moja P/Wywołania invoke wyglądają tak:

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

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

Wywołanie Instalatora zwraca się bez wyjątku, ale gdy zadzwonię do PPPConnec t, dostaję MissingMethodException - "Nie mogę znaleźć punktu wejścia" PPPConnect "w bibliotece DLL" PInvoke "PPPManager.dll."

Próbowałem usunąć dyrektywy extern i declspec z deklaracji funkcji Install, więc PPPConnect jest jedyną funkcją eksportowaną, a to nadal nie pozwala mi wywoływać PPPConnect.

Próbowałem również zrobić DllImport przez porządkowe; daje to taki sam wynik, jak wywoływanie po nazwie - Instaluje zwroty, ale PPPConnect zgłasza wyjątek "Nie można znaleźć punktu wejścia" # 2 "...".

Dziennik współdziałanie daje:

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

Jest dobrze poza moim obszarze wiedzy, więc wszelkie sugestie lub myśli byłoby mile widziane.

Dzięki, Paul

edit: Okazuje się, że ten kod działa; Problem polegał na tym, że najnowsza biblioteka dll nie była propagowana na urządzenie. D'oh!

+0

Nigdy nie słyszałem o tym dzienniku międzyoperacyjne - w jaki sposób można włączyć/zobaczyć, że? – Charlie

+0

http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx Po prostu zacząłem go używać, aby spróbować rozwiązać ten problem, ale wydaje mi się, że zaoszczędziłoby to wiele czas debugowania MissingMethodExceptions. – Symmetric

Odpowiedz

8

Czy używasz pliku .def w projekcie dll do eksportowania tych funkcji? Jeśli tak, usuń go i spróbuj ponownie. To tylko przypuszczenie, ponieważ wygląda na to, że twój wywóz nie jest tym, czym powinien być, kiedy robisz zewnętrzne "C" declspec (dllexports).

Starałem się to z prostego dll C++ z wykorzystaniem

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

i prostej aplikacji C#, używając swoich deklaracji PInvoke i to działało dobrze.

Kiedy zrobiłem DUMPBIN/eksport na dll zobaczyłem:

zrzut pliku PPPManager.dll

File Type: DLL

sekcja zawiera następujące eksportu dla 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) 

Zauważ, że wyeksportowane nazwy różnią się w moim przypadku.

+0

Ostatecznie okazało się, że nie kopiowałem najnowszej biblioteki DLL z powodu mojego nieporozumienia, co robi polecenie "Dodaj plik do projektu" w VS. Twój pomysł, aby wypróbować obnażoną bibliotekę dll był ziarnem, które musiałem przejść i wymyślić to. Dzięki! – Symmetric

+0

Świetnie! Cieszę się, że mogłem pomóc. –

0

Świetna informacja, ale jak pan wspomina, wszystko jest tutaj w porządku. Spróbuj zainstalować narzędzia do debugowania dla systemu Windows i uruchom:

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

, aby uzyskać lepszy zrzut tabeli symboli; jest to ślepy strzał, jak również, ale można też spróbować:

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

w przypadku __declspec robi coś dziwnego.

1

Może to być coś tak prostego, jak PPPConnect, które może zostać nieprawidłowo zinterpretowane przez system operacyjny. Spróbuj wdrożyć zarówno Install i PPPConnect jako no-ops (po prostu niech zwracają TRUE bez robienia niczego innego) i zobacz, czy błąd nadal występuje. Jeśli tak, spróbuj zmienić kolejność, w jakiej są eksportowane (nadal jako no-ops) i sprawdź, czy problem jest związany z zamówieniem (mało prawdopodobne) lub czymś innym.

Można również użyć narzędzia graficznego depends, aby sprawdzić, jak wygląda tabela eksportu DLL, ale wątpię, aby problem pochodził z tych kwartałów.

+0

To są dobre pomysły na wyizolowanie prawdziwego problemu. Możesz także spróbować dodać trzecią funkcję i zobaczyć, co się z nią dzieje. – Charlie

1

Zgodnie z twoim opisem Zainstaluj i PPPConnect różni się tylko imionami. Chyba po prostu używasz starej wersji .dll z aplikacją C#. Jeden bez zdefiniowanego PPPConnect.

Deklaracje wyglądają dobrze (o ile mogę oceniać bez źródeł).

0

użycie Dependency Walker i otworzyć DLL, aby sprawdzić, jakie metody są dostępne

Powiązane problemy