zoukankan      html  css  js  c++  java
  • 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 字符

    【注】

    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_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 ( " ")
        
    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=gbk
    from 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] 的值。

  • 相关阅读:
    _#【命名】 / _
    _#【插件】
    _#【命名】样式类
    linux dd命令
    python urllib2和urllib的区别
    hadoop的find
    hadoop的fs基本命令
    /etc/profile和 . profile 文件
    广告sdk
    linux下查找文件的常用命令
  • 原文地址:https://www.cnblogs.com/adylee/p/10299157.html
Copyright © 2011-2022 走看看