Python中ctypes库的学习

转自:http://blog.csdn.net/linda1000/article/details/12623527
Python中ctypes的使用整理

ctypes是Python的一个外部库,提供和C语言兼容的数据类型,可以很方便地调用C DLL中的函数。ctypes的官方文档在这里。

  1. ctypes基本数据类型映射表

参数类型预先设定好,或者在调用函数时再把参数转成相应的c_***类型。ctypes的类型对应如下:

ctypes type C type Python Type
c_char char 1-character string
c_wchar wchar_t 1-character unicode string
c_byte char int/long
c_ubyte unsigned char int/long
c_bool bool bool
c_short short int/long
c_ushort unsigned short int/long
c_int int int/long
c_uint unsigned int int/long
c_long long int/long
c_ulong unsigned long int/long
c_longlong __int64 or longlong int/long
c_ulonglong unsigned __int64 or unsigned long long int/long
c_float float float
c_double double float
c_longdouble long double float float
c_char_p char * string or None
c_wchar_p wchar_t * unicode or None
c_void_p void * int/long or None

对应的指针类型是在后面加上”_p”,如int*是c_int_p等等。在python中要实现c语言中的结构,需要用到类。

  1. 加载DLL

访问dll,首先需引入ctypes库
from ctypes import *

假设你已经有了一个的DLL(名字是add.dll),且该DLL有一个符合cdecl(这里强调调用约定是因为,stdcall调用约定和cdecl调用约定声明的导出函数,在使用python加载时使用的加载函数是不同的,后面会有说明)调用约定的导出函数Add。
stdcall调用约定:两种加载方式
[python] view plain copy
print?

Objdll = ctypes.windll.LoadLibrary("dllpath")    
Objdll = ctypes.WinDLL("dllpath")     

cdecl调用约定:也有两种加载方式
[python] view plain copy
print?

Objdll = ctypes.cdll.LoadLibrary("dllpath")    
Objdll = ctypes.CDLL("dllpath")    

其实windll和cdll分别是WinDLL类和CDll类的对象。

  1. 调用DLL方法

加载dll后会返回一个DLL对象,使用其中的函数方法则相当于操作该对象的对应属性。

注意,经过stdcall声明的方法,如果不是用def文件声明的导出函数或者extern “C” 声明的话,编译器会对函数名进行修改

函数参数申明,通过设置函数的argtypes属性

函数返回类型,函数默认返回c_int类型,如果需要返回其他类型,需要设置函数的restype属性

  1. 指针与引用

常用的通过调用ctypes类型的指针函数来创建指针实例:
[python] view plain copy
print?

from ctype import *  
i = c_int(1)  
pi = POINTER(i)  

对指针实例赋值只会改变其指向的内存地址,而不是改变内存的内容,与其他语言类似,如需要可改变内容的字符串,可须使用create_string_buffer()
[python] view plain copy
print?

>>> p = create_string_buffer("Hello", 10)  # create a 10 byte buffer  
>>> print sizeof(p), repr(p.raw)  
10 'Hello/x00/x00/x00/x00/x00'  

不带参数的调用指针类型创建一个NULL指针, NULL指针有一个False布尔值
[python] view plain copy
print?

>>> null_ptr = POINTER(c_int)()   
>>> print bool(null_ptr)   
False   

指针实例有一个contents属性,返回这个指针所指向的对象。

另外,byref()是用来传递引用参数,pointer()作为传参通常会创建一个实际的指针对象,当不需要实际指针对象时,则可使用byref()

  1. 结构体类型处理

Structures和Unions必须继承Structure和Union基础类,它们都在ctypes模块中定义,每一个子类必须定义个fields属性,fields是一个二维的tuples列表,包含着每个field的name及type,这field类型必须是一个ctypes类型,如c_int,或者任何其他的继承ctypes的类型,如Structure, Union, Array, 指针等。

例如有一个简单结构,包含两个整型x和y,可如下初始化一个结构:
[python] view plain copy
print?

from ctypes import *  
import types  
class Test(Structure):  
    _fields_ = [('x', c_int),  
                ('y', c_char)]  
test1 = Test(1, 2)  

另外,如结构体用于链表操作,即包含指向结构体指针时,若直接定义:
[python] view plain copy
print?

from ctypes import *  
import types  
class Test(Structure):  
    _fields_ = [('x', c_int),  
                ('y', c_char),  
                ('next', Test)]  

则python会报错type未定义,:
[python] view plain copy
print?

from ctypes import *  
import types  
class Test(Structure):  
    pass  
Test._fields_ = [('x', c_int),  
                ('y', c_char),  
                ('next', POINTER(Test))]  
  1. 数组定义

数组包含一个固定数目的相同类型的实例,常用创建数组类型是对一个数据类型与一个正数相乘,例如:
[python] view plain copy
print?

ArrayType = Test * 10  

[python] view plain copy
print?

初始化和使用数组:  

<span style="color:#0000ff">>>> from ctypes import *  
>>> TenIntegers = c_int * 10  
>>> ii = TenIntegers(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)  
>>> print ii  
<c_long_Array_10 object at 0x...>  
>>> for i in ii: print i,  
</span>  
  1. 回调函数

ctypes可以从python可调用对象中创建一个c可调用的函数指针,这些通常被称为回调函数。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可以使用Pythonctypesctypes结构体转换为tensor,具体的操作步骤是:1. 读取ctypes结构体;2. 使用ctypes的from_buffer()函数将ctypes结构体转换为Numpy数组;3. 使用TensorFlow的tf.convert_to_tensor()函数将Numpy数组转换为Tensor。 ### 回答2: 要将ctypes结构体转为tensor,首先需要将ctypes结构体的数据提取出来,然后将提取出的数据转换为Python列表或NumPy数组格式,最后再将其转换为PyTorch的tensor对象。 以下是一种将ctypes结构体转为tensor的示例方法: ```python import ctypes import torch import numpy as np # 定义ctypes结构体 class MyStruct(ctypes.Structure): _fields_ = [ ('a', ctypes.c_int), ('b', ctypes.c_float), ('c', ctypes.c_double) ] # 创建ctypes结构体对象 my_struct = MyStruct() # 设置ctypes结构体的数据 my_struct.a = 10 my_struct.b = 3.14 my_struct.c = 2.718 # 提取ctypes结构体的数据 data = [my_struct.a, my_struct.b, my_struct.c] # 将数据转换为NumPy数组格式 numpy_array = np.array(data) # 将NumPy数组转换为tensor对象 tensor = torch.from_numpy(numpy_array) # 打印转换后的tensor print(tensor) ``` 运行以上代码后,将输出转换后的tensor对象: ``` tensor([10.0000, 3.1400, 2.7180], dtype=torch.float64) ``` 这样,我们就成功地将ctypes结构体转为了PyTorch的tensor对象。 ### 回答3: 要将ctypes结构体转为tensor,我们需要先了解ctypes和tensor的基本概念。 ctypes是一个Python,它允许Python与C代码进行交互。它提供了许多函数和类,用于访问和操作C的数据类型和函数。 而tensor是一个多维数组,被广泛用于深度学习框架。在Python,tensor通常由科学计算如NumPy或PyTorch提供。 要将ctypes结构体转为tensor,我们可以通过以下步骤来实现: 1. 导入所需的: ```python import ctypes import numpy as np ``` 2. 定义ctypes结构体。假设我们有一个包含x和y坐标的点结构体: ```python class Point(ctypes.Structure): _fields_ = [("x", ctypes.c_float), ("y", ctypes.c_float)] ``` 3. 创建一个ctypes结构体实例,并初始化数据: ```python point = Point() point.x = 1.0 point.y = 2.0 ``` 4. 使用`ctypes.pointer()`函数获取结构体实例的指针: ```python point_ptr = ctypes.pointer(point) ``` 5. 使用`np.frombuffer()`函数将结构体指针转换为NumPy数组: ```python array = np.frombuffer(ctypes.addressof(point_ptr.contents), dtype=np.float32) ``` 6. 将数组转换为tensor: ```python tensor = torch.from_numpy(array) ``` 通过以上步骤,我们就可以将ctypes结构体转为tensor了。需要注意的是,这里的示例使用了NumPy和PyTorch,实际上你可以根据自己的需求选择其他科学计算来执行相似的操作。另外,转换过程可能还需要进行类型转换、内存对齐等操作,具体根据ctypes结构体和目标tensor的数据类型来确定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值