【问题标题】:How do I pass void* array to a C function via ctypes?如何通过 ctypes 将 void* 数组传递给 C 函数?
【发布时间】:2016-11-22 02:08:09
【问题描述】:

我在一个 dll 文件中有一个 C 函数,定义如下:

myFunction(const int a, long b, void * data, unsigned int * c, unsigned int * d, unsigned long * timestamp)

参数:

[in]: a
[in]: b
[out]: data, which is a pointer to a buffer that is maximum of 8 bytes
[out]: c, points to a buffer that receives data message length
[out]: d, pointer to a buffer which receives a message flag
[out]: timestamp, pointer to a buffer which receives message timestamp

我的python代码如下:

import ctypes

dllhandle = ctypes.WinDLL("dllFile.dll")

a = 1
b = 1738
data = ctypes.c_void_p*8
c = 0
d = 0
timestamp = 0

dllhandle.myFunction(a, b, data, c, d, timestamp)

当我运行我的 python 代码时,我收到以下错误:

ctypes.ArgumentError: argument 3: <type 'exceptions.TypeError'>: Don't know how to convert parameter 3.

我认为这与我创建数据缓冲区指针数组的方式有关。创建数据缓冲区的正确方法是什么?

【问题讨论】:

    标签: python python-2.7 dll ctypes


    【解决方案1】:

    您应该使用一个字符数组来传递您的数据。我写了这个脚本可以帮助你:

    """
    extern "C" void your_func(void* buffer, int size);
    """
    # For Python 2.7
    import ctypes
    
    BUFFER_SIZE = 256
    
    # Importing dll
    dll = ctypes.CDLL("dllFile.dll")
    
    # Defining C-arguments and output
    buffer_c_type = lambda chars: (ctypes.c_char * BUFFER_SIZE)(*map(ctypes.c_char, chars))
    size_c_type = ctypes.c_int
    restype = None # None is for 'void' as the result of your function in C
    
    # Creating C-arguments having Python variables 'buffer' and 'BUFFER_SIZE'
    buffer = "qwdeasdvwergb"
    c_buffer = buffer_c_type(buffer)
    c_size = size_c_type(BUFFER_SIZE)
    
    # Extracting your_func from dll and setting the type of returning value
    your_func = dll["your_func"]
    your_func.restype = restype
    
    # Running your_func
    your_func(c_buffer, c_size)
    

    【讨论】:

      【解决方案2】:

      以下是一个类型,空指针数组,大小为 8,不正确。

      data = ctypes.c_void_p*8
      

      相反,您需要一些数据的实例。您可以使用像data = 'abcdefg' 这样的字节字符串。这将传递字母的 8 字节 ASCII 值加上一个空终止符。

      如果data 是某种结构化数据,请考虑struct.pack

      >>> struct.pack('8B',1,2,3,4,5,6,7,8)
      '\x01\x02\x03\x04\x05\x06\x07\x08'
      

      cdtimestamp 需要是 C 类型才能保存输出值:

      c = ctypes.c_int()
      d = ctypes.c_int()
      timestamp = ctypes.c_ulong()
      

      使用byref 将对这些实例的引用传递给函数,但首先最好声明参数类型以确保将它们正确编组到 C 堆栈。

      from ctypes import * # for brevity
      dllhandle.myFunction.argtypes = c_int,c_long,c_void_p,POINTER(c_int),POINTER(c_int),POINTER(c_ulong)
      dllhandle.myFunction.restype = None # for void return
      
      dllhandle.myFunction(a, b, data, byref(c), byref(d), byref(timestamp))
      

      查看输出值:

      print c.value, d.value, timestamp.value
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多