我需要构建一个能够读取XML的软件,其中会有一个标记:
<Values type="MyParser.Parser" assembly="parser.dll" />
通过反射来实现它非常简单,但我需要找到一种方法来放置任何类型的语言,我的意思是,如果该方法是用C语言编写的,如果它是用C语言编写的程序集,则需要调用它同样。
我只能通过生成“exe”并将参数作为“命令行”发送并获取程序输出来实现。
我想知道这是否是最佳方式。这“安全”吗?还有另一种方法吗? C#可以从另一个程序集中调用方法(用另一种语言)吗?
On this page it says关于“您还可以跨平台与其他语言进行互操作”,但我不知道它究竟意味着什么。
答案 0 :(得分:1)
您实际上只声明您要读取DLL文件,而不是您想要对该值执行的操作。我假设您要实例化一个类型并在其上调用一些方法以获得我的答案。
如果它是托管DLL,通过使用Type.GetType,然后Activator.CreateInstance加载程序集,这应该非常简单。您应该为要实例化的类型定义一个接口,这样您就可以获得一个很好的强类型对象。如果你不能这样做,最好的选择可能是声明实例创建dynamic
,然后只需调用你想要的方法,让DLR做它的魔力。
如果它是非托管代码,现在事情变得棘手了。 C和其他过程语言不具有可以实例化和调用方法的类型的概念;所以你不能使用实例化对象的相同抽象。您需要区分托管代码和非托管代码。
C#有DllImport,这是你通常用来调用非托管代码的东西。但它并不是动态的,所以如果你事先不知道库和过程名,就不能使用它。
您可以使用DllImport创建一个解决方案来调用Win32本机方法LoadLibraryEx(加载DLL),然后GetProcAddress来获取指向您要调用的函数的指针。然后,您可以使用Marshal.GetDelegateForFunctionPointer
获取可以调用的C#委托。完成使用非托管库后,请不要忘记致电FreeLibrary。
答案 1 :(得分:0)
这很大程度上取决于您尝试与之互操作的内容。如果你想从另一个.NET程序集中调用一个方法,那么你可以简单地引用它(它与写入的内容无关)。
我不认为通过COM调用任意方法是可能的,但你可以声明每个可能的方法(使用相关的Interop属性)然后选择你需要使用的方法依赖于配置值。
如果外部程序集既不是.NET也不是COM,则无法直接调用其方法。
您可以构建解决方案的最具互操作性的方式是使用Web服务调用。
答案 2 :(得分:0)
经典的互操作源如下:
[System.Runtime.InteropServices.DllImport("opengl32.dll", EntryPoint = "glActiveTexture", ExactSpelling = true)]
internal extern static void glActiveTexture(int texture);
换句话说,静态例程glActiveTexture位于应用程序路径中的open32.dll二进制文件中,带有签名(EntryPoint)glActiveTexture。
有时事情并不那么容易。例如:
[System.Runtime.InteropServices.DllImport("opengl32.dll", EntryPoint = "glGetActiveUniform", ExactSpelling = true)]
internal extern static unsafe void glGetActiveUniform(uint program, uint index, Int32 bufSize, [Out]Int32 length, [Out]int size, [Out]int type, [Out]StringBuilder name);
您可以在参数前记下 [Out] 。该参数属性用于指示例程glGetActiveUniform将输出这些变量的数据,因为它们实际上是函数写入的指针。
这是为了引入互操作编组,这意味着运行时复制进出外部例程参数(即: [Out] 属性表示在例程退出时复制出变量)。
上面的代码是由我的应用程序生成的,具有函数规范(在本例中为OpenGL)。我见过类似的代码生成器,它采用了C头。
据我所知,你想要在运行时加载二进制文件。好吧......我将是一项艰巨的任务,因为必须有一种方法来为每个库使用配套配置创建这些代理,但实际上我不知道这是否适用于任何语言。
答案 3 :(得分:0)
您可以使用p-invoke来执行从dll导出的C函数。