Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 如何导出CIL DLL中的方法,以便本机程序可以调用它?_.net_Pinvoke_Cil - Fatal编程技术网

.net 如何导出CIL DLL中的方法,以便本机程序可以调用它?

.net 如何导出CIL DLL中的方法,以便本机程序可以调用它?,.net,pinvoke,cil,.net,Pinvoke,Cil,我回顾了ECMA 335,只找到了.export关键字的参考,该关键字似乎很有希望,但文档很少。关于在C#中执行此操作,我在StackOverflow上发现了类似的问题。然而,到目前为止,这些都没有让我有任何用处 >底线是:我有一个CIL DLL,我想从一个本地C++应用程序调用一些静态方法。< /P> < P>在ILAsm的新版本中,您可以简单地做: .method public static void Foo () { .export [1] // code ... }

我回顾了ECMA 335,只找到了
.export
关键字的参考,该关键字似乎很有希望,但文档很少。关于在C#中执行此操作,我在StackOverflow上发现了类似的问题。然而,到目前为止,这些都没有让我有任何用处


<> >底线是:我有一个CIL DLL,我想从一个本地C++应用程序调用一些静态方法。< /P> < P>在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:插槽。(表ID是连续的,因此取决于声明顺序。)

新的ILASM为您完成所有这些工作,前提是您不将导出表用于任何其他用途


请注意,所有这些都是非常不可移植的。

您必须将dll作为com dll公开。Com执行本机到.net互操作的工作。你只能在.net VM中运行IL代码。

到目前为止,根据我的实验,只有在方法没有任何参数的情况下,只添加.export[n]而不添加任何其他gunk就足够了。我从一个小的函数库开始,比如

[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,no[DllExport],确保相应地设置解决方案配置(Debug,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内核


最后,我不会用39.5英尺(12.04米)的杆接触COM,主要是为了避免供应商schlock。

正如Zor的解决方案所示,没有COM疯狂是可能的。如果我错了,请纠正我,但ilasm仍然生成PE MSIL文件,仍然不适合从本机应用程序调用。您仍然需要一个.net虚拟机来执行代码。没有虚拟机,托管代码无法神奇地运行,即使是通过COM调用。我的解决方案只是导出托管方法,这样,当从本机代码调用托管方法时,.NET VM会介入并执行托管代码,然后返回到本机代码。