I am playing with the .NET Core runtime hosting example.
When I build it "as is" (64 bit) on Windows, it works.
When I build it as a 32-bit application (on Windows) and change the .NET runtime to x86 (-r win-x86), it crashes.
This is what's happening. After the managedDelegate returns, the stack of the caller (main()) is corrupted and the app crashes.
doWork_ptr managedDelegate;
createManagedDelegate(
hostHandle,
domainId,
"ManagedLibrary, Version=1.0.0.0",
"ManagedLibrary.ManagedWorker",
"DoWork",
(void**)&managedDelegate);
char* ret = managedDelegate("Test job", 5, sizeof(data) / sizeof(double), data, ReportProgressCallback);
When I change the managed method (DoWork) to a void-returning one without any parameters, it works.
It seems that I am missing something about the calling conventions, but cannot spot what exactly. The default one is stdcall on Windows, but there are some differences between x86 and x64 too. x64 uses a special x64 fastcall convention, and I suspect it somehow messes up the whole thing when hosting the .NET CLR in a 32-bit app.
What do I need to change to get this running? Do I need to build the native (host) app using a specific calling convention? Do I need to decorate the managed methods with special attributes? Or maybe somehow configure the hosted .NET Core runtime?
As @HansPassant mentioned in the comments:
That is the trick.
The callback and the managed method function pointer need to be additionally decorated with the
__stdcallattribute:The callback implementation needs to be decorated too:
It turns out that the managed marshaler treats the managed methods as
__stdcallon x86, which is no surprise.Applying those changes makes the sample work when built as an x86 app hosting the x86 .NET Core runtime.