Einstellung dllimport programmgesteuert in C#
Ich bin mit DllImport
in meiner Lösung.
Mein problem ist, dass ich zwei Versionen der gleichen DLL gebaut, für 32 bit und eine für 64 bit.
Beide setzen die gleichen Funktionen mit identischen Namen und identischen Signaturen.
Mein problem ist, dass ich zwei statische Methoden, die aussetzen, und diese dann zur Laufzeit verwenden IntPtr
Größe zu bestimmen, die richtige zu berufen.
private static class Ccf_32
{
[DllImport(myDllName32)]
public static extern int func1();
}
private static class Ccf_64
{
[DllImport(myDllName64)]
public static extern int func1();
}
Habe ich zu tun, weil myDllName32
und myDllName64
muss konstant sein und ich habe nicht gefunden, einen Weg, um es zur Laufzeit.
Hat jemand eine elegante Lösung, damit konnte ich loswerden der code-Duplizierung und die ständige IntPtr
Größe überprüfen.
Wenn ich könnte den Namen der Datei, ich möchte nur noch einmal überprüfen, und ich konnte loswerden von einer Tonne wiederholt-code.
- Keinen Sinn in der Auswahl zur Laufzeit, wenn der Unterschied ist die ganze Zusammenstellung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Kann man wohl erreichen, das mit der
#if
Schlüsselwort. Wenn du definieren eines bedingten compiler-symbol genanntwin32
dem folgenden code wird die Verwendung der win32-block, wenn Sie es entfernen, wird es mit dem anderen block:Bedeutet dies wohl, dass Sie können entfernen Sie die Klasse Verpackung, die Sie jetzt haben:
Für Komfort, ich denke, man könnte erstellen build-Konfigurationen für die Steuerung der compilation-symbol.
Ich lieber tun dies, indem Sie die LoadLibrary Anruf von kernel32.dll zu zwingen, eine bestimmte DLL laden von einem bestimmten Pfad.
Wenn Sie Namen für Ihre 32-bit-und 64-bit-DLLs, die die gleichen, aber Sie in verschiedenen Pfaden haben, können Sie dann den folgenden code verwenden, laden Sie die richtige version von Windows Sie ausgeführt werden. Alles, was Sie tun müssen, ist Anruf ExampleDllLoader.LoadDll (), BEVOR code verweisen auf die ccf Klasse referenziert:
Ich weiß, das ist eine wirklich alte Frage (ich bin neu - ist es schlecht um die Antwort auf eine alte Frage?), aber ich hatte einfach zu lösen, dieses problem. Ich hatte zu dynamisch verweisen auf eine 32-bit-oder 64-bit-DLL auf Basis von OS, während meine .EXE-Datei kompiliert wird, die für Jede CPU.
Können Sie verwenden, DLLImport, und Sie brauchen nicht mit LoadLibrary().
Ich habe dies mithilfe der SetDLLDirectory. Im Gegensatz zu den Namen, die
SetDLLDirectory
fügt dem DLL-Suchpfad, und ersetzen nicht den gesamten Pfad. Dies erlaubte mir, um eine DLL mit dem gleichen Namen ("TestDLL.dll" für diese Diskussion) in Win32-und Win64-sub-Verzeichnisse und entsprechend aufgerufen.Warum nicht wickeln Sie Sie in eine Methode?
Eine alternative option ist, um sowohl die 32 - und 64-bit-Versionen von der nicht verwalteten DLL müssen den gleichen Namen haben, aber Sie Leben in separaten Ordnern in Ihren build-output (z.B. x86\ und x64\).
Dann, sich an Ihren Installateur oder wie auch immer man die Verteilung dieser wird aktualisiert, so dass es weiß, zu installieren, die entsprechende DLL für die Plattform, die es installieren.
können Sie auf zwei Methoden, und wählen Sie eine in einer Laufzeitumgebung, so dass Sie halten können
Any CPU
}
Können Sie nicht tun, wie Sie wollen. Sie müssen denken, der
DllImport
- Attribut Metadaten, die verwendet wird zur compile-Zeit. Als Ergebnis können Sie nicht ändern Sie die DLL importiert dynamisch.Wenn Sie möchten, um Ihr verwalteten code gezielt auf "Any CPU", dann muss man entweder importieren Sie sowohl die 32-bit-und 64-bit-Bibliotheken gewickelt als zwei verschiedene Funktionen, die Sie aufrufen können, abhängig von der Laufzeitumgebung oder zusätzliche Win32-API-Aufrufe zu spät-laden Sie die richtige version von der nicht verwalteten assembly zur Laufzeit und zusätzliche Win32-Aufrufe zur Ausführung der erforderlichen Methoden. Der Nachteil dort ist, dass Sie nicht haben, compile-time support für diese Art von code für die Art der Sicherheit, etc.
Hmm, ich Frage mich, ob Sie könnte eine Schnittstelle erstellen und dann eine Klasse mit den Methoden basierend auf der 32-bit-und 64-bit-dlls.
Ich bin mir nicht sicher, ob es eine explizite Methode, um zu bestimmen, wenn Sie mit 64 bit, aber Folgendes könnte funktionieren: allow unsafe code und haben eine unsichere Funktion bekommt einen Zeiger auf eine bestimmte Speicheradresse und dann bestimmen, ob der Zeiger ist 4 oder 8 bytes groß. Basierend auf den Ergebnissen bestimmen, welche implementation des interface zu erstellen.
Können Sie bestimmen, ob Sie 64 bit oder nicht, indem Sie die Größe der IntPtr-Typ (die nennt sich native int sowieso).
Sie können dann laden Sie die zugehörige DLL einen importierten LoadLibraryW-Aufruf, die Funktion Zeiger mithilfe von GetProcAddress, und dann, check-out Marschall.GetDelegateForFunctionPointer
Diese nicht annähernd so kompliziert, wie es Aussehen könnte. Sie müssen DllImport beide LoadLibraryW und GetProcAddress.