【转】python中使⽤C类型的数组以及ctypes的⽤法【转⾃】
Python 在 ctypes 中为我们提供了类似C语⾔的数据类型,
它的⽤途(我理解的)可能是:
(1)与其他语⾔(如 C、Delphi 等)写的动态连接库DLL 进⾏交换数据,因为 python 的数据与 DLL难以进⾏数据交换。
(2) python 的字符串⼀旦形成,是不可变的,为了算法的需要,我们有时需要对字符串进⾏原位操作 ( in place ),⽽不想浪费另外的内存空间。
(3) python 具有很简明的语法,⼈们乐于使⽤。在解决实际问题时,字符串的处理占据了很⼤的开发量。
互联⽹上有很多有⽤的算法可以帮助我们解决问题,如果我们能⽤python 写类似于 C 语⾔的程序,就不需要⽤其他语去写扩展了。
有⼈会问,既然如此,⽤C语⾔,不就好了吗?
当然可作这种选择,在⽤ python 的优势在于:既⽤使⽤了C语⾔的优点,也使⽤了Python的最⼤优点:垃圾⾃动回收,代码简洁等。
⼀、导⼊ C 类型库
from ctypes import *
⼆、常⽤的C 类型
(1) c_int  、 c_long 、c_int32
C 类型的long int ,这两个类型完全相同。
python ⽤ int 与之相应,但c_int的取值范围是 32 bit 的整数。
占⽤ 4 字节内存
(2) c_int64
64 bit 整数,占⽤ 8 字节内存, python ⽤ int 与之相应
(2) c_double 、c_float
C 类型的 double , 这两个名字( c_double 、c_float 完全相同)
占⽤ 8 字节内存
python ⽤ float 与之相应
(3) c_byte
C 类型的 byte ,  python ⽤ int 与之相应
占⽤1字节内存
(4) c_char
C 的 8 bit 字符型
(5) c_wchar
C 的 unicode 字符c 字符串转数组
【注】
ctypes模块
C类型                      Python类型                        ctypes 类型
char                        1-character/string                c_char
wchar_t                    1-character/Unicode、string      c_wchar
char                        int/long                          c_byte
char                        int/long                          c_ubyte
short                      int/long                          c_short
unsigned short              int/long                          c_ushort
int                        int/long                          C_int
unsigned int                int/long                          c_uint
long                        int/long                          c_long
unsigned long              int/long                          c_ulong
long long                  int/long                          c_longlong
unsigned long long          int/long                          c_ulonglong
float                      float                            c_float
double                      float                            c_double
char *(NULL terminated)    string or none                    c_char_p
wchar_t *(NULL terminated) unicode or none                  c_wchar_p
void *                      int/long or none                  c_void_p
当⼀个函数期望⼀个指针作为参数时,可以像这样调⽤
function_main( byref(parameter) ). //
struct例⼦
下⾯的例⼦是定义⼀个结构
C语⾔例⼦
struct beer_recipe
{
int amt_barley;
int amt_barley;
int amt_water;
};
Python例⼦
class beer_recipe(Structure):
_fields_ = [
("amt_barley", c_int),
("amt_water", c_int),
]
Union结构例⼦
C语⾔例⼦
union {
long barley_long;
int barley_int;
char barley_char[8];
}barley_amount;
Python例⼦
class barley_amount(Union):
_fields_ = [
("barley_long", c_long),
("barley_int", c_int),
("barley_char", c_char * 8),
]
三、⽣成类似C的数组
⽬的:初值化⼀个具有 10 个元素的数组,每个元素初值为0的
(⼀) python 原⽣数组 list
>>> a = [ 0 ] * 10>>> for i in range(0, len(a)):          print( a[i], end=" ")
0 0 0 0 0 0 0 0 0 0 >>>
(⼆)⽣成 10 元素的 c_int 类型的数组:
格式⼀:
>>> from ctypes import *
>>> a = ( c_int * 10) ()
>>> for i in range(0, len(a)):
print( a[i], end=" ")
0 0 0 0 0 0 0 0 0 0
>>>
格式⼆:
>>> from ctypes import *
>>> M = 10
>>> a = ( c_int * M ) ()
>>> for i in range(0, len(a)):
print( a[i], end=" ")
0 0 0 0 0 0 0 0 0 0
格式三:
>>> from ctypes import *
>>> myArr10 = c_int * 10
>>> a = myArr10( )
>>> for i in range(0, len(a)):
print( a[i], end=" ")
0 0 0 0 0 0 0 0 0 0
c_double 的数组定义与上⾯相似。
四、如何使⽤ C 类型的数组 ?
例 1 ,对整数数组倒序的程序
#coding=gbk
from ctypes import *
# 定义具有10个 c_int 元素的数组
# 编写⼀维数组的倒序的程序
# 说明:本算法参照⽹上基于指针的算法改写⽽成。
def outPut( A ):
for i in range(0,N):
print( A[i], end=" ")
print ( "\n")
def arrReverse( A , N):
i = 0 ; j = N-1
while i<j:
A[i], A[j] = A[j], A[i]
# 相当于 T =A[i]; A[i]=A[j]; A[j]=T
i = i+1; j=j-1
#测试程序
N = 10
a = (c_int * N )()
for i in range(0,N):
a[i] = i;
print ( "原数组:")
outPut( a )
arrReverse( a ,len(a) )
print ("倒序数组:")
outPut( a )
--- 结果 ---
原数组:
0 1 2 3 4 5 6 7 8 9
倒序数组:
9 8 7 6 5 4 3 2 1 0
例2 求倒序字符串
#coding=gbkfrom ctypes import *# 编写求字符串的倒序字符串 def arrReverse( A , N ):    i = 0 ; j = N-1    while i<j:        A[i], A[j] = A[j], A[i]        # 相当于 T =A[i]; A[i]=A[j]; A[j]=T        i = i+1; j=j-1    #测试程序        a = create_unicode_buffer( "张三买了⼀头⼩⽑驴,花了1024.05元钱。")
print ( "原字符:")    print ( a.value )arrReverse( a , len( a ) -1 )print ("倒序字符串:")print ( a.value )
-- 结果 --
原字符:张三买了⼀头⼩⽑驴,花了1024.05元钱。倒序字符串:。钱元50.4201了花,驴⽑⼩头⼀了买三张
解说
(1) create_unicode_buffer( python的字符串)
是创建⼀个 c_wchar 的数组,其长度是字符串的长度 +1 , 因为 C 的字符串是以 NULL 结尾的所以要多出⼀个元素才⾏。
c_wchar 是 unicode 字符。
(2)  如果您想创建⼀个可以装⾏下 100 个 unicode 字符的空的C_wchar 数组:
ar = create_unicode_buffer( 100+1 )
此时, ar 具有 101 个元素,但只能装 100个字符。
由于 ar 是⼀个真正的数组,我们可以对它的每个元素(字符)进⾏修改。
从 ar 中取出 python 的字符串:
s = ar.value
s 中存放的是 ar 中保存的 unicode 字符相应的字符串
向 ar 中存于字符串
ar.value = "要存⼊的字符串"
但要注意:
您向 ar 中存⼊的字符串的字符个数必须⼩于等于 len(ar) -1
(3) 如果您知道 ar 中第 i 个元素的字符编码,请使⽤ ord( ar[i] ) .
(4) 如果您想使 ar 的第 i 个元素变为 "好" 这个字符,有两种⽅法:
ar[i] = "好"
或者
ar[i] = chr(22909)
因为 , "好" 的 uncode 编码是 22909。
⼩结:
(1)从这个程序我们看到对整数数组及 unicode 字符数组的倒序,我们⽤的是相同的arrReverse 函数。
(2)调⽤ arrReverse
函数时,传递元素个数 N 时,如果是 c_wchar ( unicode ) 字符数组时,如记住最后⼀个元素是 NULL 这个问题。
( 3 ) 您会发现,我们这⾥编的程序很像 C 语⾔的指针,只不过,我们不需要⼿⼯释放动态申请的数组。
( 4 ) 但是您的算法中若⽤了⼤量的动态数组,等不及垃圾⾃动回收,⽽急于想释放数组占⽤的空间时,请使⽤ del ( ar )即可。
( 5) 最后⼀点:
C 语⾔关于字符串的操作,常使⽤指针的移动, 我们在 python 中移动的是数组的下标,这是作程序移植时常⽤的⽅法。
五、 C类型的数组与 python 的 list ⽤法上有什么区别和联系呢?
1 C 类型的数组的长度是不可变的。
2 C 类型数组的元素是可变的,即可以读写的
3 C 类型数组的元素是有类型的,即:它的每个元素的类型是相同的, ⽽ python 的 list 的元素可以是相同类型,也可以是不同类型。
4 C 类型数组除了不能⽤形如 ar[ 3:
5 ] = [] 格式的语句来删除某个⼦数组
5 C 类型数组的切⽚:
如 x = ar[3:5]
此时 x 是⼀个全新的数组,它是原数组的完全拷贝, 此时 x 有两个元素:
x[0] 中存的是 ar[3]的值
x[1] 中存的是 ar[4]的值
此后,改变 x[0] 时, ar[3] 不会改变; 改变 ar[3] 的值,也不会改变 x[0] 的值。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。