在python中使用ctypes来访问C#dll的方法

我想在我的python程序的关键部分实现C#代码,以使其更快。 它说(在Python文档和本站点上 )您可以加载动态链接库(以及PyDocs),如下所示:

cdll.LoadLibrary("your-dll-goes-here.dll")

这是我的代码中负责此function的部分:

 from ctypes import * z = [0.0,0.0] c = [LEFT+x*(RIGHT-LEFT)/self.size, UP+y*(DOWN-UP)/self.size] M = 2.0 iterator = cdll.LoadLibrary("RECERCATOOLS.dll") array_result = iterator.Program.ITERATE(z[0],z[1],c[0],c[1],self.iterations,M) z = complex(array_result[0],array_result[1]) c = complex(array_result[2],array_result[3]) last_iteration = int(round(array_result[4])) 

我使用的RECERCATOOLS.dll就是这个(C#代码,而不是C或C ++):

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using KarlsTools; public class Program { public static Array ITERATE(double z_r,double z_i,double c_r, double c_i, int iterations, double limit) { Complex z = new Complex(z_r, z_i); Complex c = new Complex(c_r, c_i); for (double i = 1; Math.Round(i) <= iterations; i++) { z = Complex.Pow(z, 2) + c; if (Complex.Abs(z) < limit) { double[] numbers = new double[] { Complex.Real(z), Complex.Imag(z), Complex.Real(c), Complex.Imag(c), i}; return numbers; } } double iter = iterations; double[] result = new double[] { Complex.Real(z), Complex.Imag(z), Complex.Real(c), Complex.Imag(c), iter}; return result; } } 

为了构建这个DLL,我在Visual Studio 2010项目上使用“Build”命令,该项目只包含这个文件和对“Karlstools”的引用,这是一个允许我使用复数的模块。

我不知道为什么,但是当我尝试运行我的Python代码时,它只会引发exception:

  [...] array_result = iterator.Program.ITERATE(z[0],z[1],c[0],c[1],self.iterations,M) File "C:\Python32\lib\ctypes\__init__.py", line 353, in __getattr__ func = self.__getitem__(name) File "C:\Python32\lib\ctypes\__init__.py", line 358, in __getitem__ func = self._FuncPtr((name_or_ordinal, self)) AttributeError: function 'Program' not found 

我需要这方面的帮助,因为即使将所有内容设置为public并将函数设置为static ,或者即使我尝试直接访问函数而未指定“Program”类,它仍然会抛出exception…我不知道问题可能在哪里。

你会发现使用ctypes从Python调用DLL的技巧大部分时间都依赖于用C或C ++编写的DLL,而不是C#。 使用C#,您可以使用CLR的整个机器,这些符号最有可能被破坏,而不是ctypes所期望的,并且您将从输出数组的垃圾收集中获得各种麻烦。

通过使用python for dot net( http://pythonnet.sf.net )连接python和C#代码时,我取得了很好的成功,你可能想试试这个。

另一方面,如果您处于纯粹的性能状态,请考虑使用Python / C API( http://docs.python.org/c-api/ )将代码重写为Python的本机C扩展。

这实际上非常简单。 只需使用NuGet将“UnmanagedExports”包添加到.Net项目中。 有关详细信息,请参阅https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports 。

然后,您可以直接导出,而无需执行COM层。 以下是示例C#代码:

 using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using RGiesecke.DllExport; class Test { [DllExport("add", CallingConvention = CallingConvention.Cdecl)] public static int TestExport(int left, int right) { return left + right; } } 

然后,您可以加载DLL并在Python中调用公开的方法(适用于2.7)

 import ctypes a = ctypes.cdll.LoadLibrary(source) a.add(3, 5) 

其他人指出,C#DLL的处理方式与本机DLL不同。

您可以选择将C#function导出为COM对象,Python可以轻松使用它。

就个人而言,我会考虑使用本机代码解决方案,但您可能过于致力于C#在此阶段改变方向。

ctypes用于加载用C编写的共享库(或者至少可以由CPU直接执行的共享库,并按照标准C约定导出它们的符号和函数参数。)C#DLL不是“普通”DLL,而是用于运行在.NET环境中。

你的选择是:

  1. 使用某种Python到.NET桥。
  2. 在C中编写DLL并使用ctypes调用函数并处理数据转换。
  3. 使用Python / C API并创建可加载的Python模块。

我不能说选项#1,我还没有这样做。 选项#2通常比选项#3更容易,因为您编写纯C代码并将其与ctypes粘合在一起。 选项#3将提供所有三个选项的最佳性能,因为它具有最低的调用开销并且在处理器上运行本机代码。

AC#DLL实际上被称为汇编,因此它完全不同。 除非有一个非常重要的原因,我建议你使用C ++