Forráslétrehozás egyéni rendezéshez
A .NET 7 egy új mechanizmust vezet be egy típus testreszabására a forrás által létrehozott interop használatakor. A P/Invokes forrásgenerátora felismeri MarshalUsingAttribute és NativeMarshallingAttribute jelzi egy típus egyéni rendezési funkcióját.
NativeMarshallingAttribute típusra alkalmazhatja, hogy jelezze az adott típus alapértelmezett egyéni rendezési beállítását. A MarshalUsingAttribute paraméterre vagy a visszatérési értékre alkalmazhatja, hogy jelezze a típus adott használatára vonatkozó egyéni rendezést, elsőbbséget élvezve a típuson esetlegesen előforduló beállítással NativeMarshallingAttribute szemben. Mindkét attribútum egy Typevagy több CustomMarshallerAttribute attribútummal megjelölt belépésipont-rendező típust vár. Mindegyik CustomMarshallerAttribute azt jelzi, hogy a megadott felügyelt típushoz MarshalModemelyik rendező implementációt kell használni.
A Marshaller implementációja
A Marshaller-implementációk állapot nélküliek vagy állapotalapúak lehetnek. Ha a rendező típusa osztály static
, állapot nélkülinek minősül. Ha értéktípusról van szó, állapotalapúnak minősül, és a rendszer a rendező egy példányát használja egy adott paraméter vagy visszatérési érték tárolására. A rendező implementációjának különböző alakzatai attól függően várhatók, hogy a rendező állapot nélküli vagy állapotalapú-e, és hogy támogatja-e a rendezést felügyeltről felügyelet nélkülire, felügyelet nélkülire vagy mindkettőre. A .NET SDK elemzőket és kódjavítókat tartalmaz a szükséges alakzatoknak megfelelő rendezők implementálásához.
MarshalMode
A MarshalMode megadott érték CustomMarshallerAttribute határozza meg a rendező implementációjának várható rendezési támogatását és alakját . Minden mód támogatja az állapot nélküli rendező implementációit. Az elem-rendezési módok nem támogatják az állapotalapú rendező implementációkat.
MarshalMode |
Várható támogatás | Állapotalapú is lehet |
---|---|---|
ManagedToUnmanagedIn | Felügyelet nélküli kezelés | Igen |
ManagedToUnmanagedRef | Felügyelet nélküli és felügyelet nélküli kezelésre van kezelve | Igen |
ManagedToUnmanagedOut | Felügyelet nélküli | Igen |
UnmanagedToManagedIn | Felügyelet nélküli | Igen |
UnmanagedToManagedRef | Felügyelet nélküli és felügyelet nélküli kezelésre van kezelve | Igen |
UnmanagedToManagedOut | Felügyelet nélküli kezelés | Igen |
ElementIn | Felügyelet nélküli kezelés | Nem |
ElementRef | Felügyelet nélküli és felügyelet nélküli kezelésre van kezelve | Nem |
ElementOut | Felügyelet nélküli | Nem |
MarshalMode.Default azt jelzi, hogy a rendező implementációt minden olyan módhoz használni kell, amelyet támogat. Ha egy konkrétabb MarshalMode
rendező implementációja is meg van adva, elsőbbséget MarshalMode.Default
élvez a .
Alapszintű használat
Megadható NativeMarshallingAttribute egy típus, amely egy osztály vagy struct
egy kezdőpont típusú rendezőre static
mutat.
[NativeMarshalling(typeof(ExampleMarshaller))]
public struct Example
{
public string Message;
public int Flags;
}
ExampleMarshaller
, a belépésipont-rendező típusa, a marshaller implementálási típusára mutatva van megjelölveCustomMarshallerAttribute. Ebben a példában ExampleMarshaller
a belépési pont és a megvalósítás is. Megfelel az értékek egyéni rendezéséhez várt rendezőalakzatoknak .
[CustomMarshaller(typeof(Example), MarshalMode.Default, typeof(ExampleMarshaller))]
internal static class ExampleMarshaller
{
public static ExampleUnmanaged ConvertToUnmanaged(Example managed)
=> throw new NotImplementedException();
public static Example ConvertToManaged(ExampleUnmanaged unmanaged)
=> throw new NotImplementedException();
public static void Free(ExampleUnmanaged unmanaged)
=> throw new NotImplementedException();
internal struct ExampleUnmanaged
{
public IntPtr Message;
public int Flags;
}
}
A ExampleMarshaller
példában egy állapot nélküli rendező, amely támogatja a rendezést felügyeltről felügyelet nélkülire és felügyelet nélküliről felügyeltre. A rendezési logikát teljes mértékben a rendező implementációja vezérli. A strukturált szerkezet MarshalAsAttribute mezőinek megjelölése nincs hatással a létrehozott kódra.
A Example
típus ezután használható a P/Invoke forrásgenerálásban. A következő P/Invoke példában ExampleMarshaller
a rendszer a paraméter felügyeltről nem felügyeltre történő felügyeletére szolgál. A rendszer a nem felügyeltről felügyeltre vonatkozó visszatérési érték marsallására is használható.
[LibraryImport("nativelib")]
internal static partial Example ConvertExample(Example example);
Ha egy másik rendezőt szeretne használni egy Example
adott típusú használathoz, adja meg MarshalUsingAttribute a használati helyen. A következő P/Invoke példában ExampleMarshaller
a rendszer a paraméter felügyeltről nem felügyeltre történő felügyeletére szolgál. OtherExampleMarshaller
a rendszer a nem felügyeltről felügyeltre történő visszatérési érték marsallására szolgál.
[LibraryImport("nativelib")]
[return: MarshalUsing(typeof(OtherExampleMarshaller))]
internal static partial Example ConvertExample(Example example);
Gyűjtemények
Alkalmazza a ContiguousCollectionMarshallerAttribute rendező belépési pont típusára, hogy azt jelezze, hogy az egybefüggő gyűjteményekhez készült. A típusnak egynél több típusparamétert kell tartalmaznia, mint a társított felügyelt típusnak. Az utolsó típusparaméter egy helyőrző, és a forrásgenerátor kitölti a gyűjtemény elemtípusának nem felügyelt típusával.
Megadhat például egyéni rendezést egy List<T>. Az alábbi kódban ListMarshaller
a belépési pont és az implementáció is szerepel. Megfelel a gyűjtemények egyéni rendezéséhez várt rendezőalakzatoknak .
[ContiguousCollectionMarshaller]
[CustomMarshaller(typeof(List<>), MarshalMode.Default, typeof(ListMarshaller<,>))]
public unsafe static class ListMarshaller<T, TUnmanagedElement> where TUnmanagedElement : unmanaged
{
public static byte* AllocateContainerForUnmanagedElements(List<T> managed, out int numElements)
=> throw new NotImplementedException();
public static ReadOnlySpan<T> GetManagedValuesSource(List<T> managed)
=> throw new NotImplementedException();
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(byte* unmanaged, int numElements)
=> throw new NotImplementedException();
public static List<T> AllocateContainerForManagedElements(byte* unmanaged, int length)
=> throw new NotImplementedException();
public static Span<T> GetManagedValuesDestination(List<T> managed)
=> throw new NotImplementedException();
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(byte* nativeValue, int numElements)
=> throw new NotImplementedException();
public static void Free(byte* unmanaged)
=> throw new NotImplementedException();
}
A ListMarshaller
példában egy állapot nélküli gyűjteményrendező található, amely támogatja a rendezést felügyeltről nem felügyeltre, illetve nem felügyeltről felügyeltre List<T>. A következő P/Invoke példában ListMarshaller
a rendszer a paraméter felügyeltről nem felügyeltre történő marshalására és a nem felügyeltről felügyeltre történő visszatérési érték marsallására szolgál. CountElementName azt jelzi, hogy az numValues
elemszámként a paramétert kell használni a nem felügyeltről felügyeltre történő visszatérési érték rendezésekor.
[LibraryImport("nativelib")]
[return: MarshalUsing(typeof(ListMarshaller<,>), CountElementName = "numValues")]
internal static partial void ConvertList(
[MarshalUsing(typeof(ListMarshaller<,>))] List<int> list,
out int numValues);
Lásd még
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: