dlimport programmatisch in c # setzen

8

Ich verwende DllImport in meiner Lösung.
Mein Problem ist, dass ich zwei Versionen der gleichen DLL für 32 Bit und eine andere für 64 Bit erstellt habe.

Beide haben dieselben Funktionen mit identischen Namen und identischen Signaturen. Mein Problem ist, dass ich zwei statische Methoden verwenden muss, die diese zur Verfügung stellen und dann zur Laufzeit IntPtr size verwenden, um den richtigen Aufruf zu bestimmen.

%Vor%

Ich muss dies tun, weil myDllName32 und myDllName64 konstant sein müssen und ich keine Möglichkeit gefunden habe, es zur Laufzeit einzustellen.

Hat jemand eine elegante Lösung dafür, damit ich die Code-Duplizierung und die konstante IntPtr Größenprüfung loswerden kann.

Wenn ich den Dateinamen festlegen könnte, müsste ich nur einmal überprüfen und ich könnte eine Tonne von wiederholtem Code loswerden.

    
Matt 23.08.2009, 23:21
quelle

9 Antworten

12

Das erreichen Sie wahrscheinlich mit dem Schlüsselwort #if . Wenn Sie ein bedingtes Compilersymbol namens win32 definieren, verwendet der folgende Code den win32-Block. Wenn Sie ihn entfernen, wird der andere Block verwendet:

%Vor%

Dies bedeutet wahrscheinlich, dass Sie das Klassenumbruch entfernen können, das Sie jetzt haben:

%Vor%

Aus praktischen Gründen könnten Sie Buildkonfigurationen erstellen, um das Kompilierungssymbol zu steuern.

    
Fredrik Mörk 23.08.2009, 23:28
quelle
16

Ich bevorzuge dies, indem ich den Aufruf LoadLibrary verwende kernel32.dll, um zu erzwingen, dass eine bestimmte DLL von einem bestimmten Pfad geladen wird.

Wenn Sie Ihre 32-Bit- und 64-Bit-DLLs gleich nennen, sie aber in unterschiedlichen Pfaden platzieren, können Sie den folgenden Code verwenden, um die richtige Version auf der Grundlage der von Ihnen ausgeführten Windows-Version zu laden. Sie müssen lediglich ExampleDllLoader.LoadDll () aufrufen, BEVOR Sie auf einen Code verweisen, der auf die ccf -Klasse verweist:

%Vor%     
Josh Sklare 13.12.2009 14:37
quelle
9

Ich weiß, das ist eine wirklich alte Frage (ich bin neu - ist es schlecht, eine alte Frage zu beantworten?), aber ich musste das gleiche Problem lösen. Ich musste dynamisch eine 32-Bit- oder 64-Bit-DLL basierend auf dem Betriebssystem referenzieren, während meine .EXE für jede CPU kompiliert wurde.

Sie können DLLImport verwenden, und Sie müssen LoadLibrary () nicht verwenden.

Ich habe dies mithilfe von SetDLLDirectory . Im Gegensatz zum Namen fügt SetDLLDirectory dem DLL-Suchpfad hinzu und ersetzt nicht den gesamten Pfad. Dies ermöglichte mir, eine DLL mit dem gleichen Namen ("TestDLL.dll" für diese Diskussion) in Win32 und Win64-Unterverzeichnissen zu haben, und entsprechend aufgerufen.

%Vor%     
deanis 01.05.2012 13:28
quelle
2

Warum nicht in eine Methode einbinden?

%Vor%     
ChaosPandion 23.08.2009 23:28
quelle
1

Eine alternative Option besteht darin, dass sowohl die 32- als auch die 64-Bit-Version der nicht verwalteten DLL denselben Namen haben, sie jedoch in separaten Ordnern in der Build-Ausgabe (z. B. x86 \ und x64 \) enthalten.

Dann wird Ihr Installationsprogramm oder, wie auch immer Sie es verteilen, aktualisiert, damit es die richtige DLL für die Plattform installieren kann, auf der es installiert wird.

    
Zack Elan 24.08.2009 00:07
quelle
1

Sie können zwei Methoden erstellen und eine in einer Laufzeitumgebung auswählen, sodass Sie Any CPU

beibehalten können %Vor%

}

    
GSerjo 26.10.2017 20:51
quelle
0

Du kannst das nicht so machen, wie du es willst. Sie müssen sich das Attribut DllImport als Metadaten vorstellen, die zum Zeitpunkt der Kompilierung verwendet werden. Daher können Sie die DLL, die es dynamisch importiert, nicht ändern.

Wenn Sie Ihren verwalteten Code auf "Beliebige CPU" richten möchten, müssen Sie entweder die 32-Bit- und die 64-Bit-Bibliotheken als zwei verschiedene Funktionen importieren, die Sie abhängig von der Laufzeitumgebung aufrufen oder verwenden können zusätzliche Win32-API-Aufrufe, um die korrekte Version der nicht verwalteten Assembly zur Laufzeit zu laden und zusätzliche Win32-Aufrufe, um die erforderlichen Methoden auszuführen. Der Nachteil besteht darin, dass Sie keine Kompilierzeitunterstützung für irgendeine Art von Code für die Typensicherheit usw. haben.

    
Scott Dorman 24.08.2009 00:37
quelle
0

Hmm, ich frage mich, ob Sie eine Schnittstelle und dann eine Klasse mit den Methoden basierend auf den 32-Bit- und 64-Bit-DLLs erstellen könnten.

Ich bin mir nicht sicher, ob es eine explizite Methode gibt, um festzustellen, ob Sie 64 Bit ausführen, aber Folgendes könnte funktionieren: Erlauben unsicheren Code und haben eine unsichere Funktion, die einen Zeiger auf eine Adresse erhält und dann bestimmt, ob der Zeiger ist 4 oder 8 Bytes groß. Basierend auf dem Ergebnis bestimmen, welche Implementierung der Schnittstelle zu erstellen.

    
Brent Scriver 17.11.2009 05:26
quelle
0

Sie können bestimmen, ob Sie 64Bits ausführen oder nicht, indem Sie die Größe des IntPtr-Typs überprüfen (der sowieso als nativer Int-Typ bezeichnet wird). Anschließend können Sie die entsprechende DLL mithilfe eines importierten LoadLibraryW-Aufrufs laden, den Funktionszeiger mithilfe von GetProcAddress abrufen und dann Marshal.GetDelegateForFunctionPointer

Das ist nicht annähernd so kompliziert, wie es aussehen könnte. Sie müssen DllImport sowohl LoadLibraryW und GetProcAddress.

    
Robert Giesecke 17.11.2009 05:36
quelle

Tags und Links