Aufruf der C ++ DLL von C ++ funktioniert, aber nicht von C #

8

Ich habe eine DLL namens tccdvc.dll, die Teil eines hier verfügbaren SDK ist:

Ссылка

Die DLL wurde in C ++ geschrieben und die Überprüfung der DLL zeigt, dass sie mit der Linker-Version 6.0 verbunden war, also nehme ich an, dass sie mit VC ++ 6.0 geschrieben wurde. Die DLL enthält keinen Quellcode, nur eine .lib-Datei und eine .h-Datei. Alle exportierten Funktionen sind als extern "C" deklariert (also kein C ++ Name Mangling) und mit APIENTRY (also __stdcall).

Ich habe ein C ++ - Programm (nicht .NET) in Visual Studio 2010 unter Windows XP SP3 (32-Bit) geschrieben, um auf diese tccdvc.dll zuzugreifen. Dies funktioniert sowohl bei Verwendung der bereitgestellten LIB-Datei als auch bei Verwendung von LoadLibrary / GetProcAddress. Ich habe auch eine C ++ - DLL geschrieben (nennen wir es mywrapper.dll), die tccdvc.dll verwendet, und wiederum zwei Versionen, eine mit der .lib-Datei, die andere mit LoadLibrary / GetProcAddress. Auch das funktioniert gut. Diese mywrapper.dll verwendet die __cdecl-Aufrufkonvention. Es enthält eine Funktion namens InitMyWrapperDLL (), die die tccdvc.dll lädt. Die Version von mywrapper.dll, die LoadLibrary / GetProcAddress verwendet, hat Code wie folgt:

%Vor%

Auch hier funktioniert das mit einem C ++ - Frontend. Beim Aufruf von C # (auf demselben Computer) gibt der Aufruf von LoadLibrary ("tccdvc.dll") jedoch NULL zurück. In C # verwende ich:

%Vor%

Beim Kompilieren von mywrapper.dll mit der bereitgestellten tccdvc.lib-Datei schlägt dies ebenfalls fehl, mit dem Fehlercode 0x8007045a (auch bekannt als 1114), was bedeutet, dass die DLL-Initialisierung fehlgeschlagen ist und mywrapper.dll als Name des DLL. Es stellt sich heraus, dass der Fehler wegen tccdvc.dll ist, die über mywrapper.dll geladen wird.

Die Verwendung der folgenden in C # schlägt ebenfalls fehl:

%Vor%

Ich habe auch "unsicher" in der Erklärung verwendet, aber das hat keinen Unterschied gemacht. Vorhersehbar, weil LoadLibrary () fehlschlägt, so dass es nicht einmal zu TCC_DVCOpen () kommt.

Um das Problem zu lokalisieren, habe ich die LoadLibrary / GetProcAddress-Version von mywrapper.dll erneut verwendet und den folgenden Code in mein C # -Programm gestellt:

%Vor%

Danach hat hdll1 einen gültigen Wert, aber hdll2 ist 0. Wenn Sie .NET 3.5 Framework verwenden, gibt GetLastError () wieder 0x8007045a zurück, aber wenn Sie .NET 4.0 verwenden, gibt GetLastError () 0 (ERROR_SUCCESS) zurück.

Ich habe Process Monitor by Sysinternals verwendet, um weitere Informationen zu erhalten, und ich kann sehen, dass tccdvc.dll erfolgreich gelesen und zugeordnet wurde. Nichts, was Process Monitor anzeigt, gibt mir einen Hinweis darauf, warum es bei der Verwendung von C # fehlschlägt, aber nicht bei der Verwendung von C ++.

Irgendwelche Ideen? Danke!

    
zarulad 05.07.2012, 13:48
quelle

2 Antworten

1

Ich habe ein paar Vorschläge für Sie:

  • Sie könnten ein C ++ / CLI-Klassenbibliotheksprojekt erstellen und dann in Ihrem C # -Projekt darauf verweisen.
  • In meinem Fall habe ich herausgefunden, dass UnmanagedFunctionPointerAttribute für den Aufruf wesentlich war,
  • Es gab einen Fall, dass, was auch immer ich tun würde, der Anruf bei der .DLL nie von C # ausging, nur die .LIB funktionierte für mich (was bedeutet, meinen ersten Vorschlag umzusetzen). Die Fehlerbehebung führte mich dazu, dass der DLL-Bereich für diese bestimmte Bibliothek nicht geeignet war.

(Zum letzten Satz: Ich bin kein C ++ - Experte, eigentlich ist das das einzige Projekt, das ich bisher gemacht habe. Das verdient sicherlich mehr Details, aber ich wusste nie und hatte nicht das Wissen, um die Ursache des Problems zu finden wurde behoben, weil ich es einfach brauchte Danke, dass du auf Fehler / bessere Erklärungen hingewiesen hast.

Hier ist eine Lösung für mein Problem:

Wie verwendet man einen C-Callback von C #? Es gibt den Link zum .DLL, wenn Sie meinen ganzen Code sehen wollen, fragen Sie einfach.

Auch ein paar Werkzeuge, die mir in diesem Bereich hilfreich gewesen sind:

Möge die Macht bei dir sein: -)

    
Aybe 09.07.2012 21:27
quelle
0

Ihr C-Code funktioniert also, wenn er aus einer C ++ - Anwendung aufgerufen wird, aber der identische Code schlägt fehl, wenn er von einer .NET-Binärdatei aufgerufen wird, wo er in LoadLibrary ...

fehlschlägt

Dies ist nur eine Ahnung, daher bin ich mir nicht sicher, ob Sie Ihre Umstände beschreiben, aber LoadLibrary hat einige komplizierte Kriterien für die Auflösung der Pfade relativer DLL-Namen, die je nach Parameter variieren können. Ich kenne sie nicht alle von oben. Es kann sein, dass etwas im EXE-Manifest der .NET-Binärdatei verhindert, dass die DLL nach diesen Regeln gefunden wird. Sie könnten versuchen, die Umgebungsvariable PATH anzupassen oder die DLL mit einem absoluten Pfad zu laden. (Sie können GetModuleFileName usw. verwenden, um den absoluten Pfad Ihres eigenen Codes zu finden ...)

    
asveikau 09.07.2012 22:52
quelle

Tags und Links