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

Dan*_*ans 9 c# python dll ctypes load

我想在我的python程序的关键部分实现C#代码,以使其更快.它说(在Python文档和本站点上)您可以加载动态链接库(以及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]))
Run Code Online (Sandbox Code Playgroud)

我使用的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;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了构建这个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
Run Code Online (Sandbox Code Playgroud)

我需要这方面的帮助,因为它不断抛出异常甚至将所有内容设置为public和函数static,甚至当我尝试直接访问函数而不指定"程序"类时...我不知道在哪里问题可能是.

小智 11

这实际上非常简单.只需使用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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

import ctypes
a = ctypes.cdll.LoadLibrary(source)
a.add(3, 5)
Run Code Online (Sandbox Code Playgroud)


gur*_*lex 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扩展.