2016-11-22 3 views
0

У меня есть функция C в файл длл определяется следующим образом:Как передать массив void * на функцию C через ctypes?

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 

Мой питон код выглядит следующим образом:

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) 

Когда я запускаю мой питон код, я получаю следующую ошибку:

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

Я решил, что это связано с тем, как я создаю свой массив указателей буфера данных. Каков правильный способ создания буфера данных?

ответ

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

Ниже приведен тип, массив указателей размера пустот 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' 

c, d, timestamp нужно быть типа 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 
Смежные вопросы