1, 首先確定你的python支持不支持ctypes
python2.7以后ctypes已經(jīng)是標(biāo)配了,2.4以后的版本得自己裝下ctypes
2,加載動(dòng)態(tài)庫(kù)
兩種加載方式
>>> from ctypes import *
>>> libc = cdll . LoadLibrary ( "libc.so.6" )
>>> libc.printf("%d",2)
>>> from ctypes import *
>>> libc = CDLL ( "libc.so.6" )
>>> libc.printf("%d",2)
3, 調(diào)用系統(tǒng)函數(shù)
上面的例子已經(jīng)調(diào)用了系統(tǒng)函數(shù)printf,這里再給幾個(gè)其他例子
>>> from ctypes import *
>>> libc = CDLL ( "libc.so.6" )
>>> print libc . time ( None )
1308019893
>>> print libc.atoi("234")
234
4,ctypes 數(shù)據(jù)類型和 C數(shù)據(jù)類型 對(duì)照表
這些數(shù)據(jù)都可以用一個(gè)默認(rèn)值進(jìn)行創(chuàng)建
>>> c_int()
c_long(0)
>>> c_char_p("Hello, World")
c_char_p('Hello, World')
>>> c_ushort(-3)
c_ushort(65533)
>>>
這些數(shù)據(jù)也可以被改變:
>>> i = c_int(42)
>>> print i
c_long(42)
>>> print i.value
42
>>> i.value = -99
>>> print i.value
-99
>>>
賦值給 c_char_p,c_wchar_p,c_void_p
只改變他們指向的內(nèi)存地址,而不是改變內(nèi)存的內(nèi)容
>>> s = "Hello, World"
>>> c_s = c_char_p(s)
>>> print c_s
c_char_p('Hello, World')
>>> c_s.value = "Hi, there"
>>> print c_s
c_char_p('Hi, there')
>>> print s # first string is unchanged
Hello, World
>>>
如果需要可改變內(nèi)容的字符串,需要使用 create_string_buffer()
>>> from ctypes import *
>>> p = create_string_buffer(3) # create a 3 byte buffer, initialized to NUL bytes
>>> print sizeof(p), repr(p.raw)
3 '/x00/x00/x00'
>>> p = create_string_buffer("Hello") # create a buffer containing a NUL terminated string
>>> print sizeof(p), repr(p.raw)
6 'Hello/x00'
>>> print repr(p.value)
'Hello'
>>> p = create_string_buffer("Hello", 10) # create a 10 byte buffer
>>> print sizeof(p), repr(p.raw)
10 'Hello/x00/x00/x00/x00/x00'
>>> p.value = "Hi"
>>> print sizeof(p), repr(p.raw)
10 'Hi/x00lo/x00/x00/x00/x00/x00'
>>>
5,函數(shù)返回類型
函數(shù)默認(rèn)返回 C int 類型,如果需要返回其他類型,需要設(shè)置函數(shù)的 restype 屬性
>>> strchr = libc.strchr
>>> strchr("abcdef", ord("d")) # doctest: +SKIP
8059983
>>> strchr.restype = c_char_p # c_char_p is a pointer to a string
>>> strchr("abcdef", ord("d"))
'def'
>>> print strchr("abcdef", ord("x"))
None
>>>
6,傳遞指針或者引用
很多情況下 C 函數(shù)需要傳遞指針或者引用,ctypes也完美的支持這一點(diǎn)
byref() 用來(lái)傳遞引用參數(shù),pointer() 函數(shù)也可以完成同樣的工作,但pointer()會(huì)創(chuàng)建一個(gè)實(shí)際的指針對(duì)象,如果你不需要一個(gè)指針對(duì)象,
用byref()會(huì)快很多
>>> i = c_int()
>>> f = c_float()
>>> s = create_string_buffer('/000' * 32)
>>> print i.value, f.value, repr(s.value)
0 0.0 ''
>>> libc.sscanf("1 3.14 Hello", "%d %f %s",... byref(i), byref(f), s)
3
>>> print i.value, f.value, repr(s.value)
1 3.1400001049 'Hello'
>>>
7,結(jié)構(gòu)體和聯(lián)合
結(jié)構(gòu)體和聯(lián)合必須從 Structure 和 Union 繼承,子類必須定義
_fields_ 屬性,_fields_ 屬性必須是一個(gè)2元組的列表,
包括一個(gè)field名字和field的類型
field類型 必須是一個(gè)ctypes的類型例如 c_int, 或者其他繼承自ctypes的類型,結(jié)構(gòu)體,聯(lián)合,數(shù)組,指針。
下面的例子演示一個(gè) POINT結(jié)構(gòu)體,包括 field X,Y
>>> from ctypes import *
>>> class POINT(Structure):.
_fields_ = [("x", c_int),
("y", c_int)]
>>> point = POINT(10, 20)
>>> print point.x, point.y
10 20
>>> point = POINT(y=5)
>>> print point.x, point.y
0 5
>>> POINT(1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1
, in ?
ValueError
: too many initializers
>>>
一個(gè)復(fù)雜點(diǎn)的例子,field類型也是一個(gè)結(jié)構(gòu)體
>>> class RECT(Structure):
... _fields_ = [("upperleft", POINT),
... ("lowerright", POINT)]
...
>>> rc = RECT(point)
>>> print rc.upperleft.x, rc.upperleft.y
0 5
>>> print rc.lowerright.x, rc.lowerright.y
0 0
>>>
多種方式進(jìn)行初始化
>>> r = RECT(POINT(1, 2), POINT(3, 4))
>>> r = RECT((1, 2), (3, 4))
8,數(shù)組
數(shù)組定義很簡(jiǎn)單
定義一個(gè)有10個(gè)POINT元素的數(shù)組
TenPointsArrayType = POINT * 10
初始化和使用數(shù)組:
>>> 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,
...
1 2 3 4 5 6 7 8 9 10
>>>
9,指針
pointer() 函數(shù)可以創(chuàng)建一個(gè)指針
Pointer實(shí)例有一個(gè) contents屬性 返回指針指向的對(duì)象
>>> from ctypes import *
>>> i = c_int(42)
>>> pi = pointer(i)
>>> pi.contents
c_long(42)
可以改變指針指向的內(nèi)容
>>> i = c_int(99)
>>> pi.contents = i
>>> pi.contents
c_long(99)
>>>
可以按數(shù)組方式訪問(wèn):
>>> pi[0]
99
>>>
按數(shù)組方式改變值
>>> print i
c_long(99)
>>> pi[0] = 22
>>> print i
c_long(22)
>>>
以上都是ctypes的基本用法,對(duì)普通的開(kāi)發(fā)人員來(lái)說(shuō),基本夠用了
更詳細(xì)的說(shuō)明請(qǐng)參考:http://docs./library/ctypes.html
|