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] 的值。

  • 相关阅读:
    The Future of Middleware and the BizTalk Roadmap
    FW: How to spawn a process that runs under the context of the impersonated user in Microsoft ASP.NET pages
    Strips illegal Xml characters
    luogu P2280 激光炸弹(二维前缀和)
    luogu P2704 炮兵阵地(经典状态压缩DP)
    SP1716 GSS3 Can you answer these queries III (线段树维护最大连续子段和)
    二分图判定、匹配问题
    C++语法综合 | 基于char*设计一个字符串类MyString
    luogu P1044 火车进出栈问题(Catalan数)
    C++设计模式 | 三种设计模式基础
  • 原文地址:https://www.cnblogs.com/adylee/p/10299157.html
Copyright © 2011-2022 走看看