dotnet / corert

This repo contains CoreRT, an experimental .NET Core runtime optimized for AOT (ahead of time compilation) scenarios, with the accompanying compiler toolchain.
http://dot.net
MIT License
2.91k stars 510 forks source link

Question about Marshalling of data structures across C++/C# #8365

Closed darderik closed 3 years ago

darderik commented 3 years ago

Hello, following the solution provided to the issue #6984 , I tried playing around with the return of data structures from C++ to C#, as i couldn't find an issue related to this kind of operation, I thought about opening one in order to receive a few heads-up on the topic.

C++ Code

struct myStruct {
    int ok;
    string testStr;
} ;
extern "C" myStruct entry() {
    myStruct myStu;
    myStu.ok = 1;
    myStu.testStr = "hello";
    return myStu;
}

C# Code

namespace CppInterop
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic ok = entry();
        }
        [DllImport("*")]
        public extern static dynamic entry();
    }
}

As expected, i get this error

Unhandled Exception: System.Exception: Method '[CppInterop]CppInterop.Program.entry()' requires marshalling that is not yet supported by this compiler.
   at CppInterop.Program.entry() + 0x30
   at CppInterop!<BaseAddress>+0x1e9b2d
Aborted

I was wondering if there was another way (as I know that dynamic isn't aot friendly at all) to pass data structures (or objects) back from cpp , in the particular case that i know exactly how is the passed object structured. Thank you for the help 👍

MichalStrehovsky commented 3 years ago

extern "C" myStruct entry()

You can't pass a myStruct with a std::string to anything, really. AFAIK the memory layout of std::string is not even stable across different versions of the C++ standard libraries (a DLL compiled with e.g. Visual C++ 6.0 would have a hard time consuming this mystruct coming from an EXE compiled with Visual Studio 2019).

You have to use C types such as char*.

public extern static dynamic entry();

This means COM marshalling - the C++ side would have to return the value as a COM interface for this to work. CoreRT doesn't support COM.

I suggest reading up on p/invoke in general. This question is not really CoreRT related.

darderik commented 3 years ago

Clear enough. I read the error so I thought that there was something in the work in order to 'marshal' complex data structures(in this case COM Interfaces). thank you