Megosztás a következőn keresztül:


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 structegy 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