[COM] Is the runtime supposed to call ComWrappers.ComputeVTables if the object is an RCW? #115317
-
Hi folks, I'm trying to pass my interface [ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("C859BA31-821B-4947-A04F-5C30C6A94B82")]
public interface IFoo
{
[PreserveSig]
int Bar([In][MarshalAs(UnmanagedType.LPStr)] string Message);
}
public class FooComWrapper : IFoo
{
public struct IFooVtbl
{
public IntPtr Bar;
}
public IntPtr Instance { get; }
public IFooVtbl Vtbl { get; }
public delegate int BarDelegate(IntPtr ptrThis, [MarshalAs(UnmanagedType.LPStr)] string Message);
public BarDelegate BarFunction { get; set; }
public FooComWrapper(IntPtr ptr)
{
Instance = ptr;
unsafe
{
Vtbl = Marshal.PtrToStructure<IFooVtbl>(new nint(*(void**)ptr.ToPointer()));
BarFunction = Marshal.GetDelegateForFunctionPointer<BarDelegate>(Vtbl.Bar);
}
}
public int Bar(string Message)
{
return BarFunction(Instance, Message);
}
}
public class FooComWrappers : ComWrappers
{
protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count)
{
ComInterfaceEntry* entry = null;
count = 0;
if (obj is FooComWrapper foo)
{
// What do I do here lmao?
count = 1;
entry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(FooComWrappers), sizeof(ComInterfaceEntry));
entry->Vtable = *(IntPtr*)foo.Instance.ToPointer();
entry->IID = typeof(IFoo).GUID;
}
return entry;
}
protected override object? CreateObject(nint externalComObject, CreateObjectFlags flags)
{
return new FooComWrapper(externalComObject);
}
protected override void ReleaseObjects(IEnumerable objects)
{
throw new NotImplementedException();
}
}
public static class Program
{
[DllImport("CppProject")] static extern int FooFactory(out IntPtr ptr);
[DllImport("CppProject")] static extern int FooFunction(IFoo foo);
[SupportedOSPlatform("Windows")]
public static void Main(string[] args)
{
ComWrappers.RegisterForMarshalling(new FooComWrappers());
if (FooFactory(out IntPtr ptrFoo) == 0)
{
if (Marshal.GetObjectForIUnknown(ptrFoo) is IFoo foo)
{
foo.Bar("RCW");
_ = FooFunction(foo); // <<<<<< Pointer passed here to unmanaged function is incorrect but computed vtable is correct
}
}
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
/cc @dotnet/interop-contrib @jkoritzinsky Is |
Beta Was this translation helpful? Give feedback.
We have a fix for this in #115436.