2016-04-01 8 views
-2

Ich versuche, einen C++/CLI-Wrapper für einige native DLLs zu erstellen. Es gibt sieben dieser DLLs und mehr in der Zukunft, also muss ich sie dynamisch laden. Sie alle haben die gleichen Funktionen. LoadLibrary und GetProcAddress funktionierten in einer nativen Anwendung hervorragend, um diese Funktionen zu laden.Wrapper für native Funktionen

Immer wenn ich eine DLL lade und initialisiere, bekomme ich AccessViolationException. Im Test mit einer C# -Konsolen-App mit ausgewählter Plattform x86.

UPDATE: Nicht sicher, warum ich unten gewählt wurde. Diese Frage wurde in keiner meiner Google-Suchen beantwortet. Ich habe eine halbe Woche lang gesucht, bevor ich überhaupt gefragt habe. Alle Fragen, die hier über dasselbe Thema gestellt werden, verwenden eine andere Methode. MSDN sagt AccessViolations in nativen Interop sind das Zeichen für schwerwiegende Programmierfehler. Ich sehe nicht, was ich falsch mache. Ich sortiere meine Strings und suche vor dem Aufruf nach nullptrs. Die Ladefunktionen scheinen zu funktionieren. Wenn ich bekannte Fehlerfunktionsnamen oder einen DLL-Pfad einfüge, von dem ich weiß, dass er falsch ist, sagt er mir, dass das Laden fehlgeschlagen ist. Wenn ich die richtigen Pfade/Funktionsnamen einstelle, sagt es, dass alles funktioniert hat, aber dann stürzt es ab, wenn ich versuche, es aufzurufen. Die Funktion TSInit, für die DLL, die ich gerade teste, tut eigentlich nichts in dieser bestimmten DLL, es könnte jedoch einige tatsächliche Arbeit für die anderen DLLs mit der gleichen Schnittstelle tun.

Update 2:

Ich denke, diese Frage nicht zu beantworten ist. Wie gesagt, es gibt mehrere DLLs mit genau der gleichen Schnittstelle. Nun, ich habe herausgefunden, dass einige von ihnen arbeiten, andere nicht. Ich überprüfte alle mit dumpbin, um zu bestätigen, dass sie alle x86 kompiliert sind und sie sind. Ich bin nicht sicher, was mit den DLLs falsch ist, die nicht funktionieren. In nativen C++ - Anwendungen funktionieren alle wie erwartet.

typedef long (WINAPI *TSRINIT)(long lType, HWND hParent, RECT *pRect); 

namespace Imagery 
{ 
    public ref class Recongizer 
{ 
public: 
    Recongizer(String^ DllPath) { LoadRecongizer(DllPath); } 
    ~Recongizer() { UnloadLibrary(); } 
    bool LoadRecongizer(String^ DllPath) 
    { 
     HInstance = ::LoadLibrary(msclr::interop::marshal_as<std::wstring>(DllPath).c_str()); 
     if (HInstance == nullptr) return false; 
     if (!LoadFunctions()) return false; 
     return true; 
    } 
    long Initalize(long lType) 
    { 
     if (HInstance == nullptr || TSInit == nullptr) return 0; 
     return TSInit(0, nullptr, nullptr); 
    } 
private: 
    void UnloadLibrary() 
    { 
     if (HInstance != nullptr) ::FreeLibrary(HInstance); 
    } 
    bool LoadFunctions() 
    { 
     TSInit = (TSRINIT)::GetProcAddress(HInstance, "TSRInit"); 
     if (TSInit == nullptr) 
     { 
      ErrorMessage = "TSRInit could not be loaded."; 
      return false; 
     } 
     return true; 
    } 
    property String^ ErrorMessage; 
private: 
    HINSTANCE HInstance{ nullptr }; 
    TSRINIT TSInit{ nullptr }; 
}; 

}

+0

Sie können keine Diagnose für solch eine vage Frage erhalten. Beginnen Sie mit * not * mit LoadLibrary(), es gibt keinen Sinn. Verknüpfen Sie einfach die Importbibliotheken dieser DLLs und schließen Sie die relevanten .h-Dateien ein. Drei weniger Ausfallarten. –

+0

Zugriffsverletzungen sind keine Magie. Sie haben zum Beispiel einen Stack-Trace. – MSalters

Antwort

0

Es könnte ein Problem mit Aufrufkonventionen sein. Stellen Sie sicher, dass alle DLLs die gleiche Aufrufkonvention verwenden (d. H. WINAPI gemäß Ihrer Definition von TSRINIT), andernfalls können Sie auf Stapelfehler stoßen, da Ihr Code und der DLL-Code möglicherweise anderes Bereinigungsverhalten erwarten. Einen Überblick finden Sie unter https://msdn.microsoft.com/en-us/library/984x0h58.aspx. Nicht sicher, warum native C++ - Anwendungen funktionieren würden - nur eine wilde Vermutung.