GVKun编程网logo

Python:SWIG与ctypes

9

在本文中,我们将详细介绍Python:SWIG与ctypes的各个方面,同时,我们也将为您带来关于day17Python区分函数和方法FunctionType、MethodType和type、Pyth

在本文中,我们将详细介绍Python:SWIG与ctypes的各个方面,同时,我们也将为您带来关于day17 Python 区分函数和方法 FunctionType 、MethodType 和 type、Python ctypes 用法集锦、Python Ctypes传递数据指针、Python ctypes参数错误的有用知识。

本文目录一览:

Python:SWIG与ctypes

Python:SWIG与ctypes

在python中,什么情况下SWIG比ctypes更好的选择是在共享库中调用入口点?假设您还没有SWIG接口文件。

两者的性能指标是什么?

答案1

小编典典

SWIG生成(相当难看)C或C
++代码。它对于简单的函数(可以直接翻译的事物)简单易用,对于更复杂的函数(例如带有输出参数的函数,需要用额外的翻译步骤来用Python表示)则相当简单易用。需要将C的位写为接口文件的一部分。对于除简单使用之外的任何内容,您都需要了解CPython及其如何表示对象-
不难,但要记住一些东西。

ctypes允许您直接访问C函数,结构和其他数据,并加载任意共享库。您不需要为此编写任何C,但是您确实需要了解C的工作原理。您可能会争辩说,它是SWIG的另一面:它不会生成代码,并且不需要在运行时进行编译器,但是对于简单使用而言,它确实需要您了解C数据类型,转换,内存管理和对齐工作。您还需要手动或自动将C结构,联合和数组转换为等效的ctypes数据结构,包括正确的内存布局。

在纯执行中,SWIG可能比ctypes更快-
因为围绕实际工作的管理是在C时在编译时完成的,而不是在Python时运行的。但是,除非您接口许多不同的C函数,但每次仅接口几次,否则开销实际上并不太明显。

在开发期间,ctypes的启动成本要低得多:您不必了解接口文件,不必生成.c文件并进行编译,也不必检出和静默警告。您只需花很少的精力就可以开始使用单个C函数,然后将其扩展为更多功能。您可以直接在Python解释器中进行测试并尝试尝试。打包大量代码有些乏味,尽管有人尝试使代码简化(例如ctypes-
configure)。

另一方面,SWIG可用于为多种语言生成包装器(除非需要填写特定于语言的详细信息,例如上面提到的自定义C代码。)当包装大量SWIG可以处理的代码时,几乎不需要帮助,代码生成也可以比等效的ctypes简单得多。

day17 Python 区分函数和方法 FunctionType 、MethodType 和 type

day17 Python 区分函数和方法 FunctionType 、MethodType 和 type

from types import FunctionType, MethodType


class Car(object):

    def __init__(self):
        pass

    def run(self):
        print("my car can run!")

    @staticmethod
    def fly(self):
        print("my car can fly!")

    @classmethod
    def jumk(cls):
        print("my car can jumk!")


c = Car()

# type(obj) 表示查看obj是由哪个类创建的.

# 实例方法
print(type(c.run))  # <class ''method''>
print(type(Car.run))  # <class ''function''>

# 静态方法
print(type(c.fly))  # <class ''function''>
print(type(Car.fly))  # <class ''function''>

# 类方法,因为类在内存中也是对象,所以调用类方法都是方法类型
print(type(c.jumk))  # <class ''method''>
print(type(Car.jumk))  # <class ''method''>


# 使用FunctionType, MethodType 来判断类型
# 实例方法
print(isinstance(c.run,MethodType)) # True
print(isinstance(Car.run,FunctionType)) # True

# 静态方法
print(isinstance(c.fly,FunctionType)) # True
print(isinstance(Car.fly,FunctionType)) # True

# 类方法
print(isinstance(c.jumk,MethodType))   # True
print(isinstance(Car.jumk,MethodType))   # True


"""结论
1. 类⽅法.不论任何情况,都是⽅法.
2. 静态方法,不论任何情况.都是函数
3. 实例方法,如果是实例访问.就是⽅法.如果是类名访问就是函数.

"""

  

Python ctypes 用法集锦

Python ctypes 用法集锦

收集关于ctypes日常使用过程中的用法记录

list转换成ctypes里面的数组

In [1]: from ctypes import *

In [2]: ls = [1,2,3,4,5]

In [3]: array = (c_int*len(ls))(*ls)

In [4]: array
Out[4]: <__main__.c_long_Array_5 at 0x276ea18de48>

In [5]: for i in array: print(i)
1
2
3
4
5

 

学习链接:

ctypes中文记录

Python Ctypes传递数据指针

Python Ctypes传递数据指针

我正在访问API,但无法获取返回的数据。两个浮点指针将指向一个数据数组。我必须假设API正常运行。不同的函数调用提供了我要检索的数据的长度。length尝试时,该值低于下面的值。

C函数头

    int function(int,float * data1,float * data2)

ctypes设置

    dll.function.argtypes = (c_int,POINTER(c_float),POINTER(c_float))
    dll.function.restypes = c_int

尝试失败1:

    x = c_float()
    y = c_float()
    status = dll.function(1,byref(x),byref(y))

程序崩溃或访问冲突写入。

尝试失败2:

    x = POINTER(c_float)()
    y = POINTER(c_float)()
    status = dll.function(1,x,y)

空指针错误

尝试失败3:

    dll.function.argtypes = (c_int,c_void_p,c_void_p)
    x = c_void_p()
    y = c_void_p()
    status = dll.function(1,y)

空指针错误

尝试失败4:

    array = c_float * length
    x = array()
    y = array()
    status = dll.function(1,byref(y))

程序崩溃

尝试5失败:

    array = c_float * length
    x = POINTER(array)()
    y = POINTER(array)()
    status = dll.function(1,y)

空指针错误或ArgumentError:预期的LP_c_float实例,而不是LP_c_float_Array_ [length]

尝试失败6:

    x = (c_float*length)()
    y = (c_float*length)()
    a = cast(x,POINTER(c_float))
    b = cast(y,POINTER(c_float))
    status = dll.function(1,a,b)

程序崩溃

我想念什么,为什么?

我相信argtypes是正确的。我正在尝试适当地与他们会面,但是仍然存在问题。我是否需要以某种方式“分配”内存?(我确定获取数据后需要释放)。

这是在Windows 7上使用Python 2.7 32位的。

我已经浏览了其他类似问题,但没有找到解决方案。我想知道现在是否可以将此问题归咎于API。

Python ctypes参数错误

Python ctypes参数错误

我用C
++编写了一个测试dll,以确保一切正常,然后再开始使用所需的更重要的dll。基本上需要两个双打并将其相加,然后返回结果。我一直在玩,并与其他测试功能一起工作,但由于错误我无法传递参数。我的代码是:

import ctypesimport stringnDLL = ctypes.WinDLL(''test.dll'')func = nDLL[''haloshg_add'']func.restype = ctypes.c_doublefunc.argtypes = (ctypes.c_double,ctypes.c_double)print(func(5.0,5.0))

它返回名为“ func”的行的错误:

ValueError: Procedure probably called with too many arguments (8 bytes in excess)

我究竟做错了什么?谢谢。

答案1

小编典典

您可能混淆了调用约定。我猜你有一个C函数声明这样的事情:

double haloshg_add(double d1, double s2){    return d1+d2;}

默认情况下,这将使用C调用约定。最简单的方法是在ctypes代码中更改调用约定:

nDLL = ctypes.CDLL(''test.dll'')

如果要将C代码中的调用约定更改为stdcall(匹配ctypes.WinDLL),则可以执行以下操作:

double __stdcall haloshg_add(double d1, double s2)

无论您做什么,都只需进行以下更改之一。如果您同时执行两个操作,则将导致反向失败!

如果是我,我只是将Python代码更改为使用C调用约定(use CDLL)。这种变化影响最小。

关于Python:SWIG与ctypes的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于day17 Python 区分函数和方法 FunctionType 、MethodType 和 type、Python ctypes 用法集锦、Python Ctypes传递数据指针、Python ctypes参数错误的相关信息,请在本站寻找。

本文标签: