I was sort of hoping for a reaction like this when I sent these patches. I think this can work, and I figure given that it can we might as well have it in Wine. I have a managed C++ hello world program generated by visual studio working with some changes to mono and the three msvcm stubs I sent.
The reason I started this is that I was blocked on making the native msvcm work with Mono, and I didn't see a way of making anything mixed-mode work without disassembling msvcm to see where it's going wrong. But I think that in the process of making mixedmodehelloworld.exe work I fixed the bug that was blocking native msvcm, and I can go back to that.
I imagine that he started working on this a while ago. Maybe he does have a plan for finishing this...
Haha, nope, I started it on Wednesday, and my plan is just to implement/fix things as they turn out to be needed.
msvcmrt? The Managed C++ Runtime DLL? I imagine you won't get far on that without a C++/CLI compiler that understands the Microsoft Visual C++ ABI--unless you're willing to write all the marshaling glue code by hand. There's only one such compiler right now, and it only runs on Windows. VC++ ABI support is on my Clang to-do list--heck, it's my GSoC project--but C++/CLI is something I won't get to for a while. Given all that, how do you intend to implement this?
The marshaling glue needs to be in Mono and mscoree, not msvcm. There are two kinds of marshaling involved: P/Invokes, which are implemented by Mono and call from CLR into native code (and some of which are a sort of "internal" pinvoke that call a function inside the same PE image, aka native code methods), and vtable fixups, which must be implemented by mscoree and will call from native code into CLR. By replacing msvcm with a builtin version, I was able to cheat a bit and run hello world without implementing vtable fixups, but I'm sure they will be needed soon.
As for doing native->CLR calls from within msvcm, there are a few options, and I haven't chosen one yet: * Build a managed helper that we can call on from msvcm. This is problematic at the moment because we do not have a free compiler able to create vtable fixups. They're not too complicated, so maybe we could implement it in Mono.Cecil. Also, if we wanted to use this with native .NET, we'd either need a way to ship CLR code with Wine. * Use the mono embedding API to essentially build our own helpers dynamically, or do what we need to do directly. This would not give us a functional msvcm with native .NET. * Use the .NET embedding API to do the same thing. This would give us a functioning msvcm with native .NET, but it means we need to implement the parts of the .NET embedding API that we need based on Mono, which would be a sizable task. * Detect whether builtin or native mscoree is being used and decide which embedding API to use based on that. Since we only need the embedding API to create CLR helpers and call CLR code that would be the same either way, this may not be so bad.
I'd like to also note that, while native msvcm contains managed code, it does not export any managed types, and mixed-mode assemblies do not even import the msvcm assembly. I had previously believed that managed exports would be required, but I now have the technology (https://github.com/madewokherd/getclrinterface) to easily see that they are not. Given that, it does not appear to be necessary for msvcm to contain any managed code.
int (__clrcall *handler)(struct _exception *)
i.e. a "pointer to a function intended to be called from managed code that takes a pointer to a struct _exception and returns an int." The definition of struct _exception is in <math.h> under Visual Studio.
I would appreciate any information you can give me about how clrcall is supposed to work. In spite of my ignorance of the specifics, I am convinced that a call from native code to clrcall is possible without a PE image containing CLR code.
To write such a function, you'd need a C++/CLI compiler.
Is this kind of like how we need a C++ compiler for msvcrt?
In this case, we don't have to write such a function at all, we get it from the caller. What we most likely need is a thunk that we can pass to __setusermatherr that will call the CLR function.
I can think of a few possibilities for what clrcall might mean. If it's some sort of object, such as a delegate, we should be able to test that, and we can definitely call it.
Whatever it is, we also will have to make sure that Mono generates the right kind of pointer. Given that Mono did attempt to call __setusermatherr_m, and given that I made some changes to Mono that I don't yet understand in order to make this work, Mono's current behavior is either Mono's best guess at the right way to do this or a random guess that I put in so I could move on.