1, 首先确定你的python支持不支持ctypes 

python2.7以后ctypes已经是标配了,2.4以后的版本得自己装下ctypes

2,加载动态库 

两种加载方式

     >>> 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, 调用系统函数 

   上面的例子已经调用了系统函数printf,这里再给几个其他例子

>>> from ctypes import *
      >>> libc = CDLL ( "libc.so.6" )
      >>> print libc . time ( None )
      1308019893
      >>> print libc.atoi("234")
      234



4,ctypes 数据类型和 C数据类型 对照表

ctypes type

C type

Python type

c_bool

_Bool

bool (1)

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_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

__int64or long long

int/long

c_ulonglong

unsigned __int64or unsigned long long

int/long

c_float

float

float

c_double

double

float

c_longdouble

long double

float

c_char_p

char *(NUL terminated)

string or None

c_wchar_p

wchar_t *(NUL terminated)

unicode or None

c_void_p

void *

int/long or None

这些数据都可以用一个默认值进行创建

>>> c_int()
 c_long(0)
 >>> c_char_p("Hello, World")
 c_char_p('Hello, World')
 >>> c_ushort(-3)
 c_ushort(65533)
 >>> 

 这些数据也可以被改变:

>>> 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 

 只改变他们指向的内存地址,而不是改变内存的内容


>>> 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
 >>> 

 如果需要可改变内容的字符串,需要使用 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,函数返回类型 

 函数默认返回 C int 类型,如果需要返回其他类型,需要设置函数的 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 函数需要传递指针或者引用,ctypes也完美的支持这一点
 byref() 用来传递引用参数,pointer() 函数也可以完成同样的工作,但pointer()会创建一个实际的指针对象,如果你不需要一个指针对象,
 用byref()会快很多

 >>> 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,结构体和联合 
 结构体和联合必须从 Structure 和 Union 继承,子类必须定义 
 _fields_ 属性,_fields_ 属性必须是一个2元组的列表,
 包括一个field名字和field的类型
 field类型 必须是一个ctypes的类型例如 c_int, 或者其他继承自ctypes的类型,结构体,联合,数组,指针。

 下面的例子演示一个 POINT结构体,包括 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
 >>> 

 一个复杂点的例子,field类型也是一个结构体

>>> 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
 >>> 

 多种方式进行初始化
>>> r = RECT(POINT(1, 2), POINT(3, 4))
 >>> r = RECT((1, 2), (3, 4)) 

8,数组 

 数组定义很简单

 定义一个有10个POINT元素的数组

TenPointsArrayType = POINT * 10 

 初始化和使用数组:

>>> 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() 函数可以创建一个指针

 Pointer实例有一个 contents属性 返回指针指向的对象

>>> from ctypes import *
 >>> i = c_int(42)
 >>> pi = pointer(i)
 >>> pi.contents
 c_long(42) 

 可以改变指针指向的内容

>>> i = c_int(99)
 >>> pi.contents = i
 >>> pi.contents
 c_long(99)
 >>> 

 可以按数组方式访问:

>>> pi[0]
 99
 >>> 

 按数组方式改变值
>>> print i
 c_long(99)
 >>> pi[0] = 22
 >>> print i
 c_long(22)
 >>>

 

以上都是ctypes的基本用法,对普通的开发人员来说,基本够用了