ctypes库

来源:互联网 发布:淘宝阿迪达斯高仿店铺 编辑:程序博客网 时间:2024/05/22 12:22

ctypes库

sf2gis@163.com

2014年9月27日

 

1 CTypes库沟通C类型与Python

1.1 基本类型

c_type:表示基本的C类型。

1.2 指针

1.2.1内建指针

c_char_p: char *

c_wchar_p: wchar_t *

c_void_p: void *

1.2.2自定义指针

POINTER(c_type): c_type类型的指针。如POINTER(c_int)表示int *。

pointer(c_type_object):c_type类型对象的指针(地址)。如a=c_int(2);pointer(2)表示&a。

注意:POINTER(c_char)和c_char_p是不同的。c_char_p指向以\0结尾的字符串,前者指向binary。

参考:https://docs.python.org/2/library/ctypes.html#ctypes.c_char_p

http://stackoverflow.com/questions/13160957/python-ctypes-and-char

1.2.3二级指针和多级指针

POINTER(POINTER(c_type)): 使用POINTER进行指针类型定义,并且可以嵌套定义二级和多级指针。如POINTER(POINTER(c_double))表示int **。

多级指针可以使用[]进行元素操作。

                pointer(pointer(c_type_object)):使用pointer可以嵌套取二级和多级指针(地址)。如pointer(pointer(a))=&(&a)

1.2.4指针的初始化和内存操作

为指针初始化的过程也就是申请内存空间的过程。申请成功后返回内存空间的起始地址。

CTypes使用(类型*个数)(初始值)格式来申请内存。

int a = (c_int*2)

1.2.5指针内容p.contents

相当于C中的*。

1.3 数组定义及初始化

(类型*内层个数*外层个数)(初始值=0)生成数组,默认为0。

1.3.1一维数组

(类型*内层个数*外层个数)(初始值=0)

a=(c_int*2)(3,4):表示a=int[2];a[0]=3,a[1]=4。

a=(c_int*2)():表示a=int[2];a[0]=0,a[1]=0。

1.3.2二维和多维数组

(类型*内层个数*外层个数)(初始值=0)

使用*由内层向外层进行定义。

 (c_int*2*3)((1,2),(5,6),(7,8))表示int[3][2],a[0]={1,2},a[1]={5,6},a[2]={7,8}。

>>> b =(c_int*2*3)((1,2),(5,6),(7,8))

>>> print b[0][0]

1

>>> print b[0][1]

2

>>> print b[1][0]

5

>>> print b[1][1]

6

>>> print b[2][0]

7

>>> print b[2][1]

8

1.4 数组/指针(一维或多维)和python list之间的转换

1.4.1将python的list(一维、多维)转换为array:

array =(c_type*n)(*list)

lstlonlat = list(((116.0,34.0), (118.5, 34.0), (120.0, 36.0)))

array2d =(c_double*2*3)(*lstlonlat)#二维数组

参考:http://stackoverflow.com/questions/4145775/how-do-i-convert-a-python-list-into-a-c-array-by-using-ctypes

1.4.2将array、指针转换为python的list

使用array的值为list赋值。

floatList = [floatPtr[i] fori in range(arrayLength)]

参考:http://stackoverflow.com/questions/19327867/convert-ctypes-byte-array-to-python-list-of-floating-point-numbers

1.4.3将二维数组、指针转换python的二维list

使用二维数组为二维list赋值。

lstTileCode =[[ppTileCode[i][j] for j in range(2)] for i in range(codecount)]

参考:http://stackoverflow.com/questions/6667201/how-to-define-two-dimensional-array-in-python

1.5 引用

byref(c_type_object) 将对象转换为引用。

速度比指针快。

1.6 指针和数组的关系与转换

p = cast(array,POINTER(type))进行类型转换。

参考:http://stackoverflow.com/questions/1363163/pointers-and-arrays-in-python-ctypes

1.6.1 一维数组和指针

指针和一维数组是不同的类型,但相互之间可以进行强制转换。

转换之后类型不同,内存地址完全不同,数据进行复制。

#一维数组和一维指针的转换

>>> a =(c_int*2)(3,4)

>>> pa =cast(a,POINTER(c_int))

>>> pa[0]

3

>>> pa[1]

4

1.6.2 二维数组和二级指针

二维数组和二级指针也可以进行转换,但转换之后的二级指针外层不为空,内层为NULL。转换只能使用赋值法进行。

#赋值法将二维数组转换为二级指针

DBL = c_double

PDBL = POINTER(DBL)

lstlonlat = list(((116.0,34.0), (118.5, 34.0), (120.0, 36.0)))

array2d =(c_double*2*3)(*lstlonlat)#二维数组

p2d0 = cast(array2d[0], PDBL)

p2d1 = cast(array2d[1], PDBL)

p2d2 = cast(array2d[2], PDBL)

p2d = (PDBL*3)(p2d0, p2d1,p2d2)#p2d就是二级指针

1.7 内存操作

1.7.1申请内存

一般的内存使用数组的初始化方法申请内存。

字符串使用create_string_buffer()来申请以\0结束的内存。raw()成员函数可以返回内存的状态。value返回内存的值。

1.7.2c_char_p,c_wchar_p,c_void_p 与create_string_buffer()之间的区别

_p代表一个指针,只能更改指针的地址,不能更改指针所指内存的内容。

create_string_buffer()所指内存内容是可以改变的。

1.8函数返回值

默认返回c_int型。如果需要其它类型,则需要设置fun.restype=c_type。(自动进行cast)。

   translatedll.lonlatList2TileCodeList.restype = POINTER(POINTER(c_int))

    ppTileCode =translatedll.lonlatList2TileCodeList(iLonLatCount, ppLonLat, iLevel,byref(iCodeCount))

    print iCodeCount

    # ppTileCode = cast(ppTileCode,POINTER(POINTER(c_int))) 如果设置了restype则自动进行cast。

1.9 class、struct、union

在python中类、结构、联合都使用class定义,但是struct继承Structure。联合继承Union。

结构的成员使用属性_fields_定义一个二维数组。

>>> classPOINT(Structure):

      _fields_ =[("lon",c_double),("lat",c_double)]

 

>>> pt = POINT(12,3)

>>> pt

<__main__.POINT object at0x027C7E90>

>>> pt.lon

12.0

1.10 参考

http://blog.csdn.net/dawnlucky/article/details/6543451

2 应用

2.1 传递字符串

使用c_char_p传递一个NULL-terminate字符串。

str = “abc”;

dll.test(c_char_p(str))

2.2 传递二维字符串

使用(c_char_p*n)()构造字符串。

2.3 传递一维数组、指针

构造一维数组传递。

由于一维数组和指针可以进行转换(参见)。所以一维数组可以传递给需要指针的参数。

    pLonLat = (c_double*4)()

   lib.mapfrmtrlib.G_MapFrmTrLib.mapFrame2LonLat(c_char_p(strCode),pLonLat)

2.4 传递二维数组

构造二维数组传递。

示例:(使用二维数组和二级指针中的方法更加快捷,这里只作演示)

DBL = c_double

PDBL = POINTER(DBL)

ppLonLat = (PDBL*3)()

lstlonlat = list(((116.0,34.0), (118.5, 34.0), (120.0, 36.0)))

print lstlonlat[0][0]

 

for i in range(3):

    ppLonLat[i] = (DBL*2)()

    for j in range(2):

        print "(i,j)=", i, j

        ppLonLat[i][j] =c_double(lstlonlat[i][j])

        print "ppLonLat(i,j)=",ppLonLat[i][j]

result =translatedll.lonlatList2TileCodeList(lonlatcount, ppLonLat, level,byref(codecount))

2.5 返回二维数组、指针

将返回的内容转换为相应的类型。或者设置restype(推荐,参见:函数返回值)。

result =translatedll.lonlatList2TileCodeList(lonlatcount, ppLonLat, level,byref(codecount))

result = cast(result,POINTER(POINTER(c_int)))

0 0