Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In .NET 7 wurde ein Quellgenerator für Plattformaufrufe eingeführt, der LibraryImportAttribute in C#-Code erkennt.
Wenn es keine Quellgenerierung verwendet, generiert das integrierte Interoperabilitätssystem in der .NET-Laufzeit zur Laufzeit einen IL-Stub — einen Datenstrom von IL-Anweisungen, der JIT-compiliert wird — um den Übergang von verwaltetem zu nicht verwaltetem Code zu erleichtern. Im folgenden Code werden das Definieren und das Aufrufen eines Plattformaufrufs (P/Invoke) gezeigt, der diesen Mechanismus verwendet:
[DllImport(
"nativelib",
EntryPoint = "to_lower",
CharSet = CharSet.Unicode)]
internal static extern string ToLower(string str);
// string lower = ToLower("StringToConvert");
Der Zwischensprache-Stub übernimmt das Marshallen von Parametern und Rückgabewerten sowie das Aufrufen des nicht verwalteten Codes unter Berücksichtigung von Einstellungen in DllImportAttribute, die sich auf das Aufrufen des nicht verwalteten Codes auswirken (beispielsweise SetLastError). Da dieser IL-Stub zur Laufzeit generiert wird, ist er für Ahead-of-Time-(AOT)-Compiler- oder IL-Trimming-Szenarien nicht verfügbar. Die Generierung der Zwischensprache ist ein wichtiger Kostenfaktor, der beim Marshallen berücksichtigt werden muss. Diese Kosten können in Bezug auf die Anwendungsleistung und die Unterstützung potenzieller Zielplattformen gemessen werden, die möglicherweise keine dynamische Codegenerierung ermöglichen. Beim Anwendungsmodell für natives AOT wird der gesamte Code im Voraus direkt als nativer Code vorkompiliert, um Probleme mit der dynamischen Codegenerierung zu vermeiden. Die Verwendung von DllImport ist keine Option für Plattformen, die vollständige native AOT-Szenarien erfordern. Daher ist die Verwendung anderer Ansätze (z. B. Quellgenerierung) besser geeignet. Das Debuggen der Marshalllogik in DllImport-Szenarien ist ebenfalls nicht zu unterschätzen.
Der im .NET 7 SDK enthaltene und standardmäßig aktivierte P/Invoke-Quellgenerator sucht nach einem LibraryImportAttribute auf einer static- und partial-Methode, um die Quellengenerierung von Marshal-Code zur Kompilierungszeit auszulösen. Dies beseitigt die Notwendigkeit, zur Laufzeit einen IL-Stub zu generieren, und ermöglicht es, dass der P/Invoke inline eingebettet werden kann.
Analysetools und Codekorrekturen sind ebenfalls enthalten, um die Migration vom integrierten System zum Quellgenerator sowie die allgemeine Nutzung zu unterstützen.
Grundlegende Verwendung
LibraryImportAttribute wird ähnlich verwendet wie DllImportAttribute. Das vorherige Beispiel kann für die Verwendung der Plattformaufruf-Quellgenerierung konvertiert werden. Hierzu wird LibraryImportAttribute verwendet und die Methode als partial (anstelle von extern) markiert:
[LibraryImport(
"nativelib",
EntryPoint = "to_lower",
StringMarshalling = StringMarshalling.Utf16)]
internal static partial string ToLower(string str);
Während der Kompilierung wird der Quellgenerator ausgelöst, um eine Implementierung der ToLower-Methode zu generieren, die das Marshallen des string-Parameters und des Rückgabewerts als UTF-16 übernimmt. Da es sich beim Marshallen nun um generierten Quellcode handelt, kann die Logik in einem Debugger untersucht und schrittweise durchlaufen werden.
MarshalAs
Der Quellgenerator berücksichtigt auch MarshalAsAttribute. Der vorherige Code kann auch wie folgt geschrieben werden:
[LibraryImport(
"nativelib",
EntryPoint = "to_lower")]
[return: MarshalAs(UnmanagedType.LPWStr)]
internal static partial string ToLower(
[MarshalAs(UnmanagedType.LPWStr)] string str);
Einige Einstellungen für MarshalAsAttribute werden nicht unterstützt. Der Quellgenerator gibt einen Fehler aus, wenn Sie versuchen, nicht unterstützte Einstellungen zu verwenden. Weitere Informationen finden Sie unter Unterschiede zu DllImport.
Aufrufkonvention
Verwenden Sie UnmanagedCallConvAttribute, um die Aufrufkonvention anzugeben. Beispiel:
[LibraryImport(
"nativelib",
EntryPoint = "to_lower",
StringMarshalling = StringMarshalling.Utf16)]
[UnmanagedCallConv(
CallConvs = new[] { typeof(CallConvStdcall) })]
internal static partial string ToLower(string str);
Unterschiede zu DllImport
LibraryImportAttribute ist in den meisten Fällen als einfache Konvertierung von DllImportAttribute gedacht, es gibt jedoch einige bewusste Änderungen:
- Für CallingConvention gibt es keine Entsprechung in LibraryImportAttribute. UnmanagedCallConvAttribute sollte stattdessen verwendet werden.
- CharSet (für CharSet) wurde durch StringMarshalling (für StringMarshalling) ersetzt. ANSI wurde entfernt, und UTF-8 ist jetzt als erstklassige Option verfügbar.
- Für BestFitMapping und ThrowOnUnmappableChar gibt es keine Entsprechung. Diese Felder waren nur beim Marshallen einer ANSI-Zeichenfolge unter Windows relevant. Der generierte Code zum Marshallen einer ANSI-Zeichenfolge weist das entsprechende Verhalten von
BestFitMapping=falseundThrowOnUnmappableChar=falseauf. - Für ExactSpelling gibt es keine Entsprechung. Dieses Feld war eine Windows-orientierte Einstellung und hatte keine Auswirkungen auf Windows-fremde Betriebssysteme. Der Methodenname oder EntryPoint muss exakt der Schreibweise des Einstiegspunktnamens entsprechen. Dieses Feld wurde in der Vergangenheit im Zusammenhang mit den Suffixen
AundWaus der Win32-Programmierung verwendet. - Für PreserveSig gibt es keine Entsprechung. Dieses Feld war eine Windows-orientierte Einstellung. Der generierte Code wandelt die Signatur immer direkt um.
- Das Projekt muss mit AllowUnsafeBlocks als unsicher gekennzeichnet werden.
Es gibt auch Unterschiede bei der Unterstützung einiger Einstellungen in MarshalAsAttribute, beim standardmäßigen Marshallen bestimmter Typen sowie bei anderen interoperabilitätsbezogenen Attributen. Weitere Informationen finden Sie in der Dokumentation zu Kompatibilitätsunterschieden.