Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use bidirectional marshallers for elements. #90056

Merged
merged 5 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ internal struct MARSHALLED_UNICODE_STRING
[CustomMarshaller(typeof(MARSHALLED_UNICODE_STRING), MarshalMode.ElementIn, typeof(Marshaller))]
public static class Marshaller
{
public static MARSHALLED_UNICODE_STRING ConvertToManaged(Native unmanaged)
{
MARSHALLED_UNICODE_STRING m;
m.Length = unmanaged.Length;
m.MaximumLength = unmanaged.MaximumLength;
m.Buffer = Marshal.PtrToStringUni(unmanaged.Buffer)!;
return m;
}

public static Native ConvertToUnmanaged(MARSHALLED_UNICODE_STRING managed)
{
Native n;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ internal struct HttpHeader
[CustomMarshaller(typeof(HttpHeader), MarshalMode.ElementIn, typeof(Marshaller))]
public static class Marshaller
{
public static HttpHeader ConvertToManaged(WEB_SOCKET_HTTP_HEADER unmanaged)
{
HttpHeader m;
m.Name = Marshal.PtrToStringAnsi(unmanaged.Name, (int)unmanaged.NameLength);
m.Value = Marshal.PtrToStringAnsi(unmanaged.Value, (int)unmanaged.ValueLength);
return m;
}

public static WEB_SOCKET_HTTP_HEADER ConvertToUnmanaged(HttpHeader managed)
{
WEB_SOCKET_HTTP_HEADER n;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -423,21 +423,33 @@ public static ITypeSymbol ReplaceGenericPlaceholderInType(ITypeSymbol managedTyp
public static bool ModeUsesManagedToUnmanagedShape(MarshalMode mode)
=> mode is MarshalMode.Default
or MarshalMode.ManagedToUnmanagedIn
or MarshalMode.UnmanagedToManagedOut
or MarshalMode.ElementIn
or MarshalMode.UnmanagedToManagedOut
or MarshalMode.ElementOut
or MarshalMode.ManagedToUnmanagedRef
or MarshalMode.UnmanagedToManagedRef
or MarshalMode.ElementRef;

public static bool ModeUsesUnmanagedToManagedShape(MarshalMode mode)
=> mode is MarshalMode.Default
or MarshalMode.ManagedToUnmanagedOut
or MarshalMode.UnmanagedToManagedIn
or MarshalMode.ElementOut
or MarshalMode.UnmanagedToManagedIn
or MarshalMode.ElementIn
or MarshalMode.ManagedToUnmanagedRef
or MarshalMode.UnmanagedToManagedRef
or MarshalMode.ElementRef;

// These modes can be used with either shape,
// but we don't want to require that all marshallers implement both shapes.
// The CustomMarshallerAttributeAnalyzer will provide any enforcement we would like
// on these marshaller shapes.
private static bool ModeOptionallyMatchesShape(MarshalMode mode)
=> mode is MarshalMode.Default
or MarshalMode.ElementIn
or MarshalMode.ElementRef
or MarshalMode.ElementOut;

private static CustomTypeMarshallerData? GetStatelessMarshallerDataForType(ITypeSymbol marshallerType, MarshalMode mode, ITypeSymbol managedType, bool isLinearCollectionMarshaller, Compilation compilation, Func<ITypeSymbol, MarshallingInfo>? getMarshallingInfo)
{
(MarshallerShape shape, StatelessMarshallerShapeHelper.MarshallerMethods methods) = StatelessMarshallerShapeHelper.GetShapeForType(marshallerType, managedType, isLinearCollectionMarshaller, compilation);
Expand All @@ -446,7 +458,7 @@ or MarshalMode.UnmanagedToManagedRef
ITypeSymbol? nativeType = null;
if (ModeUsesManagedToUnmanagedShape(mode))
{
if (mode != MarshalMode.Default && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer) && !shape.HasFlag(MarshallerShape.ToUnmanaged))
if (!ModeOptionallyMatchesShape(mode) && !shape.HasFlag(MarshallerShape.CallerAllocatedBuffer) && !shape.HasFlag(MarshallerShape.ToUnmanaged))
return null;

if (isLinearCollectionMarshaller && methods.ManagedValuesSource is not null)
Expand All @@ -469,7 +481,7 @@ or MarshalMode.UnmanagedToManagedRef
if (ModeUsesUnmanagedToManagedShape(mode))
{
// Unmanaged to managed requires ToManaged either with or without guaranteed unmarshal
if (mode != MarshalMode.Default && !shape.HasFlag(MarshallerShape.GuaranteedUnmarshal) && !shape.HasFlag(MarshallerShape.ToManaged))
if (!ModeOptionallyMatchesShape(mode) && !shape.HasFlag(MarshallerShape.GuaranteedUnmarshal) && !shape.HasFlag(MarshallerShape.ToManaged))
return null;

if (isLinearCollectionMarshaller)
Expand Down Expand Up @@ -501,7 +513,7 @@ or MarshalMode.UnmanagedToManagedRef
}

// Bidirectional requires ToUnmanaged without the caller-allocated buffer
if (mode != MarshalMode.Default && ModeUsesManagedToUnmanagedShape(mode) && ModeUsesUnmanagedToManagedShape(mode) && !shape.HasFlag(MarshallerShape.ToUnmanaged))
if (!ModeOptionallyMatchesShape(mode) && ModeUsesManagedToUnmanagedShape(mode) && ModeUsesUnmanagedToManagedShape(mode) && !shape.HasFlag(MarshallerShape.ToUnmanaged))
return null;

if (nativeType is null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ public static void ThrowOnNthUnmarshalledElement(int n)

public static IntStructWrapper ConvertToManaged(nint unmanaged) => s_IntStructWrapperMarshalling.ConvertToManaged(unmanaged);

public static nint ConvertToUnmanaged(IntStructWrapper managed) => throw new NotImplementedException();

/// <summary>
/// The number of elements that are expected to be cleaned up / freed.
/// </summary>
Expand Down Expand Up @@ -366,6 +368,8 @@ public static void ThrowOnNthUnmarshalledElement(int n)

public static BoolStruct ConvertToManaged(nint unmanaged) => s_BoolStructMarshalling.ConvertToManaged(unmanaged);

public static nint ConvertToUnmanaged(BoolStruct managed) => throw new NotImplementedException();

/// <summary>
/// The number of elements that are expected to be cleaned up / freed.
/// </summary>
Expand All @@ -390,10 +394,10 @@ public static void Free(nint obj)
/// so the pinvoke should not be run if it will access marshalled objects. Make sure to call ThrowOnNthMarshalledElement such that marshalling
/// the array will fail before the pinvoke is run.
/// </summary>

[CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStruct))]
[CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementRef, typeof(EnforceLastElementMarshalledCleanupBoolStruct))]
[CustomMarshaller(typeof(BoolStruct), MarshalMode.ElementOut, typeof(EnforceLastElementMarshalledCleanupBoolStruct))]
[CustomMarshaller(typeof(char), MarshalMode.ElementIn, typeof(EnforceLastElementMarshalledCleanupBoolStruct))]
static class EnforceLastElementMarshalledCleanupBoolStruct
{
private static MarshallingExceptionManager<BoolStruct> s_BoolStructMarshalling = new(_dummyPtr, default);
Expand All @@ -410,8 +414,6 @@ public static void Free(nint obj)
s_BoolStructMarshalling.Throw($"Freed unmarshalled pointer: {obj}");
}

public static nint ConvertToUnmanaged(char managed) => throw new NotImplementedException();

public static BoolStruct ConvertToManaged(nint unmanaged) => throw new NotImplementedException();
}

Expand Down
Loading