在python中使用ctypes访问c# dll's方法

本文关键字:dll 方法 访问 python ctypes | 更新日期: 2023-09-27 18:02:11

我想在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]))

我使用的recercatols .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,或者即使当我试图直接访问函数而不指定"程序"类…我不知道问题出在哪里

在python中使用ctypes访问c# dll's方法

这其实很简单。只需使用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)

你会发现关于使用ctypes从Python调用DLL的提示大部分时间依赖于用C或c++编写的DLL,而不是c#。在c#中,您引入了CLR的整个机制,并且符号很可能是混乱的,而不是ctypes所期望的,并且您将从输出数组的垃圾收集中获得各种麻烦。

当使用python for。net (http://pythonnet.sf.net)连接python和c#代码时,我已经取得了非常好的成功,你可能想尝试一下。

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

其他人指出c# DLL不能像本地DLL那样被对待。

你的一个选择是将c#功能导出为一个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将提供所有三个选项中最好的性能,因为它具有最低的调用开销并且在处理器上运行本机代码。

c# DLL实际上被称为程序集,因此它是完全不同的。除非有非常重要的原因,否则我建议您使用c++