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

COM/OO Interop #23

Closed
mterwoord opened this issue Jun 30, 2020 · 14 comments
Closed

COM/OO Interop #23

mterwoord opened this issue Jun 30, 2020 · 14 comments
Labels
question Further information is requested

Comments

@mterwoord
Copy link

Does .NET Core support COM marshalling of objects passed around?

In .NET 4.7, one can use https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports to call methods and then return (and pass in) pointers to objects, which are callable from both sides, using COM marshalling.

@AaronRobinsonMSFT AaronRobinsonMSFT added the question Further information is requested label Jun 30, 2020
@AaronRobinsonMSFT
Copy link
Owner

Does .NET Core support COM marshalling of objects passed around?

@mterwoord That is a good question. It does support marshalling IUnknown based types on Windows only. There has been talk about enabling more support for that (see dotnet/runtime#36582). The legacy built-in support is also possible, but much more work. All of these decision are customer driven so if that is important the runtime team needs to hear it.

In .NET 4.7, one can use https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports to call methods and then return (and pass in) pointers to objects, which are callable from both sides, using COM marshalling.

Yep. The DllExport library I am familiar with is at https://github.com/3F/DllExport which seems to be a continuation of the one referenced above. The approach in this code base is a bit different but the desired end result is the same. I have some ideas on how to enable a more natural object oriented approach using DNNE and am planning on working on it in the coming weeks/months.

/cc @jkotas

@AaronRobinsonMSFT AaronRobinsonMSFT changed the title Interop COM/OO Interop Jun 30, 2020
@mterwoord
Copy link
Author

mterwoord commented Jul 11, 2020

I tried exporting a method taking a COM interface as argument, but then the build says Method 'SetEngine' has non-exportable type 'Non-primitive'.
How can I go forward here?

@AaronRobinsonMSFT
Copy link
Owner

@mterwoord The current marshalling of types in DNNE is non-existent so only primitive types are supported - DNNE doesn't support blittable structs or string types either. This is primarily because of time since there are some things that would be relatively easy to support (i.e. string and blittable structs). The IUnknown interface is a bit more complicated to do automatically - at least how I would like to do it.

One of the goals of this project was to ensure cross-platform support. Since IUnknown isn't supported by the runtime on all platforms the current built-in system for using IUnknown is probably not going to happen. I assume the focus here is on Windows so we do have the manual approach as an option.

  1. Update the argument type to be IntPtr

  2. Use Marshal.GetTypedObjectForIUnknown to get an object for the passed in IntPtr.

The approach therefore would be expose native APIs with C friendly data types, do all the marshalling manually, and then call the actual .NET API. An example using string is below. The below approach would be the same for IUnknown or even structs.

public class NativeExports
{
    [UnmanagedCallersOnly]
    public static int StringLength(IntPtr strUtf8)
    {
        if (strUtf8 == IntPtr.Zero)
            return -1;
        var str = Marshal.PtrToStringUTF8(strUtf8);
        return str.Length;
    }
}

@mterwoord
Copy link
Author

My use case is a legacy system (Delphi 6 based) calling into .NET.

Do you have any pointers to get IUnknown interface working automatically, even if there are limitations to that?
Is this something https://github.com/SharpGenTools/SharpGenTools could help me with?

@AaronRobinsonMSFT
Copy link
Owner

@mterwoord SharpGenTools is a great option for generating this code. It doesn't provide the native exports though. Getting SharpGenTools and DNNE to share types shouldn't be too hard, but the signature requirements would remain (i.e. IntPtr not the type).

I work with @jkoritzinsky who has been maintaining the SharpGenTools project. Perhaps he has some ideas on how to integrate them efficiently.

@webczat
Copy link

webczat commented Aug 7, 2020

how would marshalling work? I thought that UnmanagedCallersOnly requires all method params to be blittable...

@jkoritzinsky
Copy link
Collaborator

For SharpGenTools usage with DNNE, you'd need to write a small stub that does some manual marshalling at any API boundaries that you want DNNE to export. SharpGenTools only generates code that consumes COM, it doesn't support automatically producing new entry points (and also the native->managed direction still could use some additional work).

@mterwoord
Copy link
Author

Following up on this. I got COM marshalling working, I just needed to export the methods with parameter type IntPtr and use Marshal.GetObjectForIUnknown or Marshal.GetIUnknownForObject.

Now the only thing left for me to get working, before this really gets useful to me, is self-contained deployment.
Have you guys looked into this already?

@AaronRobinsonMSFT
Copy link
Owner

I got COM marshalling working, I just needed to export the methods with parameter type IntPtr and use Marshal.GetObjectForIUnknown or Marshal.GetIUnknownForObject.

@mterwoord Yep. Manual marshalling is the best way given DNNE is primarily focused on only exposing exports. What is nice at this point is you can decide what way is most beneficial to you. Using the above APIs you are leveraging the built-in system, but you could also decide in the future to use SharpGenTools or some other tooling.

[...] self-contained deployment. Have you guys looked into this already?

This is still of interest. We know how it can be done but simply need enough customer feedback to support it. The DNNE tooling is design to be an add on to .NET and will consume any features that become available to improve its UX. I would file an issue on the dotnet/runtime repo asking about self-contained libraries. The people to tag are @vitek-karas and @agocke.

@mterwoord
Copy link
Author

@AaronRobinsonMSFT Thanks for answering during holiday season!

I Kind-of got things working. If I put a runtime folder structure in my folder, and include the correct stuff there, things just work. Not completely "self-contained" as it involves manual code and some manual loading steps, but works well enough for me. (Of course, out of the box self-contained support would still be preferred)

@vitek-karas
Copy link
Collaborator

@mterwoord Just curious about your scenario: We currently don't support multiple CoreCLR runtimes in one process, that's why general self-contained support for libraries (we call these scenarios components sometimes as well) is not available (since if a process would load two self-contained libraries, it would need to load two runtimes -> unsupported). It would work only if you could somehow guarantee that the native process will only ever load your one library which uses .NET Core. As @AaronRobinsonMSFT mentions above, this is mostly about customer demand - if it turns out it's relatively common to have exactly one .NET Core component in a process, then the lack of SxS runtimes doesn't matter.

@mterwoord
Copy link
Author

My situation is having a handful of Delphi 6 legacy apps, which are extended using 1 (set of) .net libraries. This is 1 .net environment, not multiple.

@AaronRobinsonMSFT
Copy link
Owner

@mterwoord I am going to close this issue as I've finally gotten around to adding a simple example for how to do this: https://github.com/AaronRobinsonMSFT/DNNE/blob/master/test/ExportingAssembly/InstanceExports.cs. I think there is an opportunity to fully automate this process using a Roslyn source generator but I don't think that is in scope for this specific project.

@mterwoord
Copy link
Author

Thanks for the demo!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants