Native C++ use C# dll via proxy C++ managed dll

2019-07-21 18:06发布

问题:

This is rather convoluted, so bear with me. I have a 3rd party program (the "target") that is coded in Native (Win32 only) C++. As part of the target's design, it implements a dll-plugin system. Native DLLs, when placed in the "ext" directory of the program, are loaded by the target. The target then invokes four methods that each DLL provides (Initialize, SendHook, RecvHook, Terminate) as appropriate. As you may have guessed from the function names, the add-ins hook certain functions in the target. I do not have the source code to the target.

One of the add-ins is old and buggy - not to mention confusing and rather ugly. It's written in Delphi (compiled as a win32 DLL, of course). Over the past few weeks, I've been enhancing and translating the add-in to C# (I'll call this the "extension"). It's now complete, so I've turned my attention to getting the target to load the extension (which is built as a class library).

Obviously, the target (being native C++) cannot load the extension (managed C#) directly. So, after looking into it, it seems I simply need a "proxy" DLL (written in VC++ with CLR support) that will load my extension and then take care of passing method calls from the target to the extension.

"Simple." Yeah, right. I'm now more confused than a chameleon in a bag of Skittles. I've seen stuff about using COM, which is decidedly what I need to avoid, both in terms of performance and process-memory rights as the extension will invoke some methods (passed by handle to the proxy). Also, I've seen stuff about tlb and #import directives. This doesn't seem like the right way to go, either.

I came across this article https://sites.google.com/site/srinivasnzd/csincppviacpp-cli which seems to be at last on the right track. Indeed, I can call my managed C# from the C++ proxy just fine. As a bonus, it appears (I haven't been able to test it with the actual target yet) that the __declspec(dllexport) functions can appropriately call their managed counterparts though the proxy. But now the questions have begun popping off.

  • Can a purely native process load a CLR-enabled DLL? I've seen someone(s) talk about essentially making a static lib out of the CLR-enabled code and then linking that with a pure native code to from a "partial managed, partial native" proxy DLL. But at that point, the confusion started setting in and I wasn't sure the topic was even applicable to what I'm trying to do.
  • How do I go about marshaling a DWORD address to an IntPtr (and then un-marshaling it to a function pointer on the C# side)
  • I saw mentions of AppDomains. Is this something I need to worry about?
  • I'm assuming my proxy DLL will need to have the managed extension DLL in the same folder to run. Do I need to do anything special to load it, or will the CLR and linker take care of that?
  • In addition to the output DLL, I'm getting files with extensions of ".exp", ".ilk", and ".lib". I assume these are for static linking and I can just ignore them when I use the DLL?

回答1:

Have a look at this template for exporting the C# code with some help without using the C++ wrapper.
Unfortunately out of the box there is no DllExport attribute, thus you need either a C++ wrapper or you need to modify the IL code for performing the export.
Marshalling addresses is no issue, just be careful with function pointers on the C# side, because you always need to ensure that there is a reference to keep them away from the GC collector. It is easiest if you keep a static reference - the GC can not see references to the function pointer in the unmanaged code and thus it might clean it up.
App domains would matter if you have several c# modules - it would become more an issue if these share the same code.
The exp is coming from the linker, ilk and lib are related to the linker, thus I would expect that you do not need to copy them, but you might need them when debugging.



标签: c# dll c++-cli clr