3

这是相当复杂的,所以请耐心等待。我有一个用本机(仅限 Win32)C++ 编码的第 3 方程序(“目标”)。作为目标设计的一部分,它实现了一个 dll 插件系统。本地 DLL 当放置在程序的“ext”目录中时,由目标加载。然后目标调用每个 DLL 提供的四种方法(Initialize、SendHook、RecvHook、Terminate)。正如您可能从函数名称中猜到的那样,加载项挂钩目标中的某些函数。我没有目标的源代码。

其中一个加载项是旧的和错误的 - 更不用说令人困惑而且相当丑陋。它是用 Delphi 编写的(当然,编译为 win32 DLL)。在过去的几周里,我一直在增强插件并将其翻译为 C#(我将其称为“扩展”)。现在已经完成了,所以我将注意力转向让目标加载扩展(构建为类库)。

显然,目标(本机 C++)无法直接加载扩展(托管 C#)。因此,在研究之后,似乎我只需要一个“代理”DLL(用 VC++ 编写并支持 CLR)来加载我的扩展,然后负责将方法调用从目标传递到扩展。

“简单的。” 是的,对。我现在比吃吃喝玩乐袋里的变色龙还要困惑。我已经看到了关于使用 COM 的东西,这绝对是我需要避免的,无论是在性能还是进程内存权限方面,因为扩展将调用一些方法(通过句柄传递给代理)。此外,我还看到了有关 tlb 和 #import 指令的内容。这似乎也不是正确的方法。

我看到这篇文章https://sites.google.com/site/srinivasnzd/csincppviacpp-cli似乎终于走上了正轨。事实上,我可以从 C++ 代理调用我的托管 C# 就好了。作为奖励,看起来(我还没有能够用实际目标对其进行测试)这些__declspec(dllexport)函数可以通过代理适当地调用它们的托管对应物。但现在问题已经开始浮出水面。

  • 纯本机进程能否加载启用 CLR 的 DLL?我见过有人谈论基本上从启用 CLR 的代码中创建一个静态库,然后将其与纯本机代码链接到“部分托管、部分本机”代理 DLL。但在那一点上,混乱开始出现,我不确定这个话题是否适用于我正在尝试做的事情。
  • 如何将 DWORD 地址编组到 IntPtr (然后将其解组到 C# 端的函数指针)
  • 我看到提到 AppDomains。这是我需要担心的事情吗?
  • 我假设我的代理 DLL 需要在同一文件夹中运行托管扩展 DLL。我需要做一些特殊的事情来加载它,还是 CLR 和链接器会处理这个问题?
  • 除了输出 DLL,我还得到了扩展名为“.exp”、“.ilk”和“.lib”的文件。我假设这些是用于静态链接的,当我使用 DLL 时我可以忽略它们吗?
4

1 回答 1

2

看看这个模板,在不使用 C++ 包装器的情况下,在一些帮助下导出 C# 代码。
不幸的是,开箱即用没有 DllExport 属性,因此您需要一个 C++ 包装器,或者您需要修改 IL 代码以执行导出。
编组地址没有问题,只需小心 C# 端的函数指针,因为您始终需要确保存在引用以使它们远离 GC 收集器。如果您保留一个静态引用,这是最简单的 - GC 无法在非托管代码中看到对函数指针的引用,因此它可能会清理它。
如果您有多个 c# 模块,应用程序域将很重要——如果它们共享相同的代码,这将成为一个更大的问题。
exp 来自链接器,ilk 和 lib 与链接器相关,因此我希望您不需要复制它们,但在调试时可能需要它们。

于 2012-07-02T05:50:52.133 回答