Sdílet prostřednictvím


Generování zdrojového kódu pro vyvolání platformy

.NET 7 zavádí generátor zdrojů pro volání nespravovaného LibraryImportAttribute kódu v jazyce C#.

Pokud nepoužívá generování zdroje, integrovaný systém vzájemné spolupráce v modulu runtime .NET generuje zástupný kód IL – datový proud instrukcí IL, který je za běhu – a usnadňuje tak přechod ze spravovaného na nespravované. Následující kód ukazuje definování a následné volání nespravovaného kódu, který používá tento mechanismus:

[DllImport(
    "nativelib",
    EntryPoint = "to_lower",
    CharSet = CharSet.Unicode)]
internal static extern string ToLower(string str);

// string lower = ToLower("StringToConvert");

Zástupný kód IL zpracovává zařazování parametrů a návratové hodnoty a volá nespravovaný kód při zachování nastavení DllImportAttribute , která ovlivňují způsob vyvolání nespravovaného kódu (například SetLastError). Vzhledem k tomu, že se tento zástupný kód IL generuje za běhu, není k dispozici pro scénáře oříznutí předem (AOT) ani pro ořezávání IL. Generování IL představuje důležité náklady, které je třeba zvážit při zařazování. Tyto náklady je možné měřit z hlediska výkonu aplikace a podpory potenciálních cílových platforem, které neumožňují dynamické generování kódu. Nativní aplikační model AOT řeší problémy s dynamickým generováním kódu předkompilováním veškerého kódu předem přímo do nativního kódu. Použití DllImport není možnost pro platformy, které vyžadují úplné nativní scénáře AOT, a proto je vhodnější použít jiné přístupy (například generování zdroje). Ladění logiky zařazování ve DllImport scénářích je také netiktivní cvičení.

Generátor zdrojového kódu P/Invoke, který je součástí sady .NET 7 SDK a povolený ve výchozím nastavení, hledá LibraryImportAttribute static a partial metodu pro aktivaci generování kódu pro kompilaci a zařazování kódu, což odstraňuje potřebu generování zástupných procedur IL za běhu a umožňuje inlinovat volání nespravovaného kódu. Analyzátory a opravy kódu jsou také zahrnuty, aby pomohly s migrací z integrovaného systému do generátoru zdrojů a obecně s využitím.

Základní použití

Tato LibraryImportAttribute funkce je navržená tak, aby byla podobná DllImportAttribute použití. Předchozí příklad můžeme převést na použití generování zdroje P/Invoke pomocí LibraryImportAttribute metody a označení metody jakopartial:extern

[LibraryImport(
    "nativelib",
    EntryPoint = "to_lower",
    StringMarshalling = StringMarshalling.Utf16)]
internal static partial string ToLower(string str);

Během kompilace se spustí generátor zdroje, který vygeneruje implementaci ToLower metody, která zpracovává zařazování parametru string a návratovou hodnotu jako UTF-16. Vzhledem k tomu, že se teď vygeneruje zdrojový kód, můžete se na logiku v ladicím programu podívat a projít si ji.

MarshalAs

Zdroj generátoru také MarshalAsAttributerespektuje . Předchozí kód lze také napsat takto:

[LibraryImport(
    "nativelib",
    EntryPoint = "to_lower")]
[return: MarshalAs(UnmanagedType.LPWStr)]
internal static partial string ToLower(
    [MarshalAs(UnmanagedType.LPWStr)] string str);

Některá nastavení MarshalAsAttribute nejsou podporovaná. Pokud se pokusíte použít nepodporovaná nastavení, generátor zdroje vygeneruje chybu. Další informace naleznete v tématu Rozdíly z knihovny DllImport.

Konvenci

Pokud chcete zadat konvenci volání, použijte UnmanagedCallConvAttributenapříklad:

[LibraryImport(
    "nativelib",
    EntryPoint = "to_lower",
    StringMarshalling = StringMarshalling.Utf16)]
[UnmanagedCallConv(
    CallConvs = new[] { typeof(CallConvStdcall) })]
internal static partial string ToLower(string str);

Rozdíly od DllImport

LibraryImportAttribute má být ve většině případů jednoduchým převodem DllImportAttribute , ale existují některé záměrné změny:

  • CallingConvention nemá žádný ekvivalent dne LibraryImportAttribute. UnmanagedCallConvAttribute místo toho by se měla použít.
  • CharSet (pro CharSet) byla nahrazena písmenem StringMarshalling (pro StringMarshalling). ANSI byl odebrán a UTF-8 je nyní k dispozici jako prvotřídní možnost.
  • BestFitMapping a ThrowOnUnmappableChar nemají žádný ekvivalent. Tato pole byla relevantní pouze při zařazování řetězce ANSI ve Windows. Vygenerovaný kód pro zařazování řetězce ANSI bude mít ekvivalentní chování BestFitMapping=false a ThrowOnUnmappableChar=false.
  • ExactSpelling nemá žádný ekvivalent. Toto pole bylo nastavení zaměřené na Windows a nemělo žádný vliv na operační systémy jiné než Windows. Název metody nebo EntryPoint by měl být přesným pravopisem názvu vstupního bodu. Toto pole má historické použití související s A příponami a W příponami používanými v programování win32.
  • PreserveSig nemá žádný ekvivalent. Toto pole bylo nastavení zaměřené na Windows. Vygenerovaný kód vždy přímo přeloží podpis.
  • Projekt musí být označený jako nebezpečný pomocí AllowUnsafeBlocks.

Existují také rozdíly v podpoře některých nastavení MarshalAsAttribute, výchozí zařazování určitých typů a dalších atributů souvisejících s interoperabilitou. Další informace najdete v naší dokumentaci k rozdílům v kompatibilitě.

Viz také