如何通过ctypes将void *数组传递给C函数?

时间:2016-11-22 02:08:09

标签: python python-2.7 dll ctypes

我在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.

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

2 个答案:

答案 0 :(得分:0)

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

"""
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)

答案 1 :(得分:0)

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

data = ctypes.c_void_p*8

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

如果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