ctypes库
2014年9月27日
c_type:表示基本的C类型。
c_char_p: char *
c_wchar_p: wchar_t *
c_void_p: void *
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
POINTER(POINTER(c_type)): 使用POINTER进行指针类型定义,并且可以嵌套定义二级和多级指针。如POINTER(POINTER(c_double))表示int **。
多级指针可以使用[]进行元素操作。
pointer(pointer(c_type_object)):使用pointer可以嵌套取二级和多级指针(地址)。如pointer(pointer(a))=&(&a)
为指针初始化的过程也就是申请内存空间的过程。申请成功后返回内存空间的起始地址。
CTypes使用(类型*个数)(初始值)格式来申请内存。
int a = (c_int*2)
相当于C中的*。
(类型*内层个数*外层个数)(初始值=0)生成数组,默认为0。
(类型*内层个数*外层个数)(初始值=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。
(类型*内层个数*外层个数)(初始值=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
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
使用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
使用二维数组为二维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
byref(c_type_object) 将对象转换为引用。
速度比指针快。
p = cast(array,POINTER(type))进行类型转换。
参考:http://stackoverflow.com/questions/1363163/pointers-and-arrays-in-python-ctypes
指针和一维数组是不同的类型,但相互之间可以进行强制转换。
转换之后类型不同,内存地址完全不同,数据进行复制。
#一维数组和一维指针的转换
>>> a =(c_int*2)(3,4)
>>> pa =cast(a,POINTER(c_int))
>>> pa[0]
3
>>> pa[1]
4
二维数组和二级指针也可以进行转换,但转换之后的二级指针外层不为空,内层为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就是二级指针
一般的内存使用数组的初始化方法申请内存。
字符串使用create_string_buffer()来申请以\0结束的内存。raw()成员函数可以返回内存的状态。value返回内存的值。
_p代表一个指针,只能更改指针的地址,不能更改指针所指内存的内容。
create_string_buffer()所指内存内容是可以改变的。
默认返回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。
在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
http://blog.csdn.net/dawnlucky/article/details/6543451
使用c_char_p传递一个NULL-terminate字符串。
str = “abc”;
dll.test(c_char_p(str))
使用(c_char_p*n)()构造字符串。
构造一维数组传递。
由于一维数组和指针可以进行转换(参见)。所以一维数组可以传递给需要指针的参数。
pLonLat = (c_double*4)()
lib.mapfrmtrlib.G_MapFrmTrLib.mapFrame2LonLat(c_char_p(strCode),pLonLat)
构造二维数组传递。
示例:(使用二维数组和二级指针中的方法更加快捷,这里只作演示)
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))
将返回的内容转换为相应的类型。或者设置restype(推荐,参见:函数返回值)。
result =translatedll.lonlatList2TileCodeList(lonlatcount, ppLonLat, level,byref(codecount))
result = cast(result,POINTER(POINTER(c_int)))