AaronRobinsonMSFT / DNNE

Prototype native exports for a .NET Assembly.
MIT License
406 stars 41 forks source link

Return COM interface from Unmanaged Export? #81

Closed obiwanjacobi closed 3 years ago

obiwanjacobi commented 3 years ago

I am trying to implement a factory method that returns a COM compatible interface:

Steinberg::IPluginFactory* __stdcall GetPluginFactory()

I have implemented a decorated managed representation of the IPluginFactory interface and have a C++/CLI project working with this interface. The goal was to get rid of the C++/CLI interop assembly and hopefully make this work cross-platform.

I am currently getting a CS8894 error saying that the return type cannot be used. I understand it's not blittable. Is there any chance of getting this scenario (COM interface) working?

https://github.com/obiwanjacobi/vst.net/tree/master/Source3/Code

AaronRobinsonMSFT commented 3 years ago

The goal was to get rid of the C++/CLI interop assembly and hopefully make this work cross-platform.

@obiwanjacobi Laudable goal and one I fully support. The key here is to recognize that the runtime isn't going to do anything automatically for you when using DNNE. This library is a low level tool that could be coupled with a source generation mechanism that could perform the manual tasks for you though.

The manual part that needs to happen is the following:

[UnmanagedCallersOnly]
public static IntPtr GetPluginFactory()
{
    var factory = new PluginFactory();

    // Ask the runtime to create a CCW.
    IntPtr pUnk = Marshal.GetIUnknownForObject(factory);

    // Request the default interface - IPluginFactory
    var iid =  typeof(IPluginFactory).GUID;
    int hr = Marshal.QueryInterface(null, ref iid, out IntPtr pFact);
    Debug.Assert(hr == 0);

    // Release the IUnknown
    Marshal.Release(pUnk);
    return pFact;
}
obiwanjacobi commented 3 years ago

Ah - of course (I knew that!) Thanks very much.

Edit: Works on windows! :thumbsup:

I'm getting CA1416 warnings on the Marshal calls. Any hints or tips on how to get that cross-platform? - a bit off-topic perhaps...

Edit: Are the ComWrappers API cross-platform? The class is tagged with 'Windows' only in the docs, but I remember reading somewhere on a github issue you said they were. So...?

AaronRobinsonMSFT commented 3 years ago

@obiwanjacobi That is great to hear. ComWrappers was made cross-platform in .NET 6. For .NET 5, it is only supported on Windows. The Marshal calls are potentially still marked for Windows-only on .NET 6. There are some rough edges in this due to the long history of support. Once more people are on .NET 6 I am anticipate we will get a large number of requests to fix the various CA1416 issues.