Skip to content

Commit

Permalink
Marshal object as IUnknown (#1089)
Browse files Browse the repository at this point in the history
  • Loading branch information
kant2002 authored May 7, 2021
1 parent 5f54b68 commit c24a981
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,22 @@ public static IntPtr ConvertManagedComInterfaceToNative(object pUnk, Guid interf
#endif
}

public static IntPtr ConvertManagedComInterfaceToIUnknown(object pUnk)
{
if (pUnk == null)
{
return IntPtr.Zero;
}

#if TARGET_WINDOWS
#pragma warning disable CA1416
return ComWrappers.ComInterfaceForObject(pUnk);
#pragma warning restore CA1416
#else
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
#endif
}

public static object ConvertNativeComInterfaceToManaged(IntPtr pUnk)
{
if (pUnk == IntPtr.Zero)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ internal static MarshallerKind GetMarshallerKind(
if (nativeType == NativeTypeKind.AsAny)
return isAnsi ? MarshallerKind.AsAnyA : MarshallerKind.AsAnyW;
else
return MarshallerKind.Invalid;
return MarshallerKind.ComInterface;
}
else if (InteropTypes.IsStringBuilder(context, type))
{
Expand Down
66 changes: 40 additions & 26 deletions src/coreclr/tools/Common/TypeSystem/Interop/IL/Marshaller.Aot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -878,37 +878,51 @@ protected override void AllocAndTransformManagedToNative(ILCodeStream codeStream
{
ILEmitter emitter = _ilCodeStreams.Emitter;

MethodDesc helper = Context.GetHelperEntryPoint("InteropHelpers", "ConvertManagedComInterfaceToNative");
LoadManagedValue(codeStream);
CustomAttributeValue<TypeDesc>? guidAttributeValue = (this.ManagedParameterType as EcmaType)?
.GetDecodedCustomAttribute("System.Runtime.InteropServices", "GuidAttribute");
if (guidAttributeValue == null)
var parameterType = this.ManagedParameterType;
if (parameterType.IsByRef)
{
throw new NotSupportedException();
parameterType = ((ByRefType)this.ManagedParameterType).ParameterType;
}

var guidValue = (string)guidAttributeValue.Value.FixedArguments[0].Value;
Span<byte> bytes = Guid.Parse(guidValue).ToByteArray();
codeStream.EmitLdc(BinaryPrimitives.ReadInt32LittleEndian(bytes));
codeStream.EmitLdc(BinaryPrimitives.ReadInt16LittleEndian(bytes.Slice(4)));
codeStream.EmitLdc(BinaryPrimitives.ReadInt16LittleEndian(bytes.Slice(6)));
for (int i = 8; i < 16; i++)
codeStream.EmitLdc(bytes[i]);

MetadataType guidType = Context.SystemModule.GetKnownType("System", "Guid");
var int32Type = Context.GetWellKnownType(WellKnownType.Int32);
var int16Type = Context.GetWellKnownType(WellKnownType.Int16);
var byteType = Context.GetWellKnownType(WellKnownType.Byte);
var sig = new MethodSignature(
MethodSignatureFlags.None,
genericParameterCount: 0,
returnType: Context.GetWellKnownType(WellKnownType.Void),
parameters: new TypeDesc[] { int32Type, int16Type, int16Type, byteType, byteType, byteType, byteType, byteType, byteType, byteType, byteType });
MethodDesc guidCtorHandleMethod =
guidType.GetKnownMethod(".ctor", sig);
codeStream.Emit(ILOpcode.newobj, emitter.NewToken(guidCtorHandleMethod));
CustomAttributeValue<TypeDesc>? guidAttributeValue = (parameterType as EcmaType)?
.GetDecodedCustomAttribute("System.Runtime.InteropServices", "GuidAttribute");
if (guidAttributeValue != null)
{
var guidValue = (string)guidAttributeValue.Value.FixedArguments[0].Value;
Span<byte> bytes = Guid.Parse(guidValue).ToByteArray();
codeStream.EmitLdc(BinaryPrimitives.ReadInt32LittleEndian(bytes));
codeStream.EmitLdc(BinaryPrimitives.ReadInt16LittleEndian(bytes.Slice(4)));
codeStream.EmitLdc(BinaryPrimitives.ReadInt16LittleEndian(bytes.Slice(6)));
for (int i = 8; i < 16; i++)
codeStream.EmitLdc(bytes[i]);

MetadataType guidType = Context.SystemModule.GetKnownType("System", "Guid");
var int32Type = Context.GetWellKnownType(WellKnownType.Int32);
var int16Type = Context.GetWellKnownType(WellKnownType.Int16);
var byteType = Context.GetWellKnownType(WellKnownType.Byte);
var sig = new MethodSignature(
MethodSignatureFlags.None,
genericParameterCount: 0,
returnType: Context.GetWellKnownType(WellKnownType.Void),
parameters: new TypeDesc[] { int32Type, int16Type, int16Type, byteType, byteType, byteType, byteType, byteType, byteType, byteType, byteType });
MethodDesc guidCtorHandleMethod =
guidType.GetKnownMethod(".ctor", sig);
codeStream.Emit(ILOpcode.newobj, emitter.NewToken(guidCtorHandleMethod));

MethodDesc helper = Context.GetHelperEntryPoint("InteropHelpers", "ConvertManagedComInterfaceToNative");
codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));
}
else
{
if (!parameterType.IsObject)
{
throw new NotSupportedException();
}

codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));
MethodDesc helper = Context.GetHelperEntryPoint("InteropHelpers", "ConvertManagedComInterfaceToIUnknown");
codeStream.Emit(ILOpcode.call, emitter.NewToken(helper));
}

StoreNativeValue(codeStream);
}
Expand Down

0 comments on commit c24a981

Please sign in to comment.