【发布时间】:2012-01-22 00:25:01
【问题描述】:
我已经查看了 ECMA 335,但我只找到了对 .export 关键字的引用,这似乎很有希望,但文档很少。我在 StackOverflow 上发现了关于在 C# 中执行此操作的类似问题。然而,到目前为止,这些都没有让我有任何用处。
底线是:我有一个 CIL DLL,我想从本机 C++ 应用程序调用它的一些静态方法。
【问题讨论】:
我已经查看了 ECMA 335,但我只找到了对 .export 关键字的引用,这似乎很有希望,但文档很少。我在 StackOverflow 上发现了关于在 C# 中执行此操作的类似问题。然而,到目前为止,这些都没有让我有任何用处。
底线是:我有一个 CIL DLL,我想从本机 C++ 应用程序调用它的一些静态方法。
【问题讨论】:
在较新版本的 ILAsm 中,您只需执行以下操作:
.method public static void Foo ()
{
.export [1]
// code ...
}
这会在导出表中的索引 1 处导出 Foo。导出序号应该是唯一且连续的。
在旧版本中,您必须这样做:
.data vt = int32 (0) [n]
.vtfixup [n] int32 fromunmanaged at vt
.method public static void Foo ()
{
.vtentry 1:1
.export [1]
// code ...
}
(其中“n”是您想要的导出数量。)
.vtentry 表示将方法存储在哪个 vtable:slot 中。(表 ID 是连续的,因此取决于声明顺序。)
如果您不将导出表用于其他任何事情,较新的 ILAsms 会为您完成所有这些工作。
请注意,所有这些都非常不便携。
【讨论】:
您必须将您的 dll 公开为 com dll。 Com 完成了本地到 .net 互操作的工作。除了 .net VM,你不能在任何地方运行 IL 代码。
【讨论】:
到目前为止,根据我的实验,仅当方法没有任何参数时,仅添加 .export [n] 而没有任何其他垃圾就足够了。我从一个小型函数库开始,比如
[DllExport]
public static double fooz(double arg) {
return arg + 42;
}
[DllExport]
public static int foo0(int arg) {
return arg + 42;
}
[DllExport]
public static ulong foo1(ulong arg) {
return arg + 42;
}
只用.export 就看到我的函数没有崩溃,而是忽略了它们的参数。
看看 Robert Giesecke 的 UnmanagedExports 的使用,它在 Visual Studio 中以 Nuget 包的形式提供。我发现它相当有气质和微妙,除非我从一开始就正确配置,有时它不会构建调试或将其放置在发布等中。其他人还有其他迭代加上一些进一步的开发,从 Nuget 菜单中都可以看到。我从最简单的开始,用VS2015、VS2017、VS2019试了一下。当您有一个 DLL 时,您可以使用 IL 反汇编程序更仔细地检查它,ildasm.
首先将它编译为普通的 C# DLL,不要 [DllExport],请务必相应地设置解决方案配置(调试,x64)。然后使用 ildasm 进入并查看引擎盖下的内容。从小事做起。
下一步是再次尝试使用 [DllExport] 并查看进行了哪些更改。我使用了 WinMerge。必须准确了解此工具的作用,而不是盲目地使用它并期望一切都能自动运行。
至于函数参数,为了测试,我坚持用最简单的方法,先用 VBA 测试 DLL。
Declare PtrSafe Function fooz Lib "C:\Users\bill\source\repos\Test3\bin\x86\Debug\Test3.dll" (ByVal arg As Double) As Double
由于我的 Excel 只有 32 位,配套的 DLL 必须具有相同的位数,因此是 x86。
如果您有任何复杂的参数和结果(byte[] 及以上),您将需要使用某种我尚未完全掌握的编组。想想 JSON 或 MsgPack 或其中之一的字节数组。
下一步是看看这是否适用于 Linux 下的 .Net Core。
最后,我不会用 39.5 英尺 (12.04m) 的杆子接触 COM,主要是为了避免供应商 schlock。
【讨论】: