我想在我的python程序的关键部分实现C#代码,以使其更快。它说(在Python文档和this site上)您可以加载动态链接库(以及PyDocs),如下所示:
cdll.LoadLibrary("your-dll-goes-here.dll")
这是我的代码中负责此功能的部分:
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代码时,它只会引发异常:
[...]
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
,或者即使我尝试直接访问函数而未指定“程序”课......我不知道问题出在哪里。
答案 0 :(得分:10)
实际上很容易。只需使用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)
答案 1 :(得分:7)
关于使用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扩展。
答案 2 :(得分:3)
其他人指出,C#DLL的处理方式与本机DLL不同。
您拥有的一个选项是将C#功能导出为可以由Python轻松使用的COM对象。
就个人而言,我会考虑使用本机代码解决方案,但您可能过于致力于C#在此阶段改变方向。
答案 3 :(得分:1)
ctypes
用于加载用C编写的共享库(或至少可由CPU直接执行的共享库,并按照标准C约定导出其符号和函数参数。)C#DLL不是“正常” DLL,而是打算在.NET环境中运行。
您的选择是:
ctypes
调用该函数并处理数据转换。我不能说选项#1,我还没有这样做。选项#2通常比选项#3更容易,因为您编写纯C代码并将其粘贴到ctypes
。选项#3将提供所有三个选项的最佳性能,因为它具有最低的调用开销并且在处理器上运行本机代码。
答案 4 :(得分:1)
C#DLL实际上被称为程序集,因此它完全不同。 除非有一个非常重要的原因,我建议你使用C ++