代码之家  ›  专栏  ›  技术社区  ›  Pygmalion

将指向连续数据的指针从Python传递到C的最简单方法

  •  0
  • Pygmalion  · 技术社区  · 4 年前

    我正在使用 ctypes 调用函数 C . 函数需要指向连续数据的第一个元素和数据数的指针。

    有一件事是这样的

    a=15 # a could be any number
    temp = numpy.array([a]*14, dtype=numpy.int8)
    c_function(temp.ctypes.data_as(ctypes.c_void_p), 14)
    

    这真的很麻烦,两者都需要 numpy C类型 bytes([a]*14) 但仅适用于蟒蛇3)

    a=15 # a could be any number
    temp = chr(a)*14
    c_function(temp, 14)
    

    在其他线程中,有人建议可以传递指向连续数据的第一个元素的指针,如下所示 Passing memoryview to C function ,但我就是没办法做到。

    0 回复  |  直到 4 年前
        1
  •  0
  •   John Bollinger    4 年前

    预备工作

    Python没有指针。不能在Python中创建指针,尽管Python变量在某些方面与指针类似。您可以创建 代表 较低级别的指针,但实际上您似乎想要的是向C函数提供一个指向Python管理的数据的指针,这是完全不同的事情。

    ctypes为您做什么

    根据 ctypes Python 2 docs ,在Python 2中,

    None 、整数、长字符串、字节字符串和unicode字符串是唯一的 本机Python对象,可以直接用作这些 没有 unicode字符串作为指向 ( char * wchar_t * ). [...]

    差不多是同一张单子 in Python 3 ...

    、整数、字节对象和(unicode)字符串

    ... 具有相同的语义。

    本身 甚至没有直接的表达。

    在许多C实现中,所有对象指针类型都具有相同的表示形式,可以半互换地使用,但指针类型 由标准保证 具有与类型指针相同的大小和表示形式 void * . 这两种指针类型保证可以互换为函数参数和返回值等。

    合成

    多方便啊!可以使用类型为的第一个参数调用C函数 字符* 当函数声明该参数为 ,这正是当Python参数是字节字符串(python2)或字节对象(python3)时ctypes将为您安排的内容。C函数将接收指向对象数据的指针,而不是指向对象本身的指针。这提供了一种比使用numpy或类似软件包更简单、更好的方法,基本上就是您在问题后面附加的方法。因此,假设 c_function

    len = 15
    c_function(b'0' * len, len)
    

    当然,您也可以为对象创建一个变量并传递它,这样您就可以在以后看到C函数对对象内容所做的任何操作。

    1. 就Python而言,字节字符串和字节对象是不可变的。如果您使用C函数来更改bytes对象的内容,而其他Python代码假定这些内容永远不会更改,那么您可能会遇到麻烦。

    2. C端无法通过指向它的指针来确定数据的大小。这大概就是第二个参数的用途。如果您告诉函数对象比实际大小大,并且函数依赖于此尝试修改超过实际数据结尾的字节,那么您将很难调试问题,从其他数据的损坏到内存泄漏。如果幸运的话,你的程序会崩溃。

    3. 这取决于您使用的Python实现,但通常Unicode字符串的元素都大于一个字节。省去一些麻烦,改用字节串/字节。