2016-08-15 3 views
4

Я использую ctypes для вызова иностранных функций в Python3.Чтение C структур в Python с ctypes

Функция C должна возвращать указатель на структуру:

struct sLinkedList { 
    void* data; 
    struct sLinkedList* next; 
}; 

typedef struct sLinkedList* LinkedList; 

И функция, как она определена в C выглядит следующим образом.

LinkedList IedConnection_getServerDirectory (IedConnection self, IedClientError * error, bool  getFileNames) 

Так у меня Python3 код следующим образом:

from ctypes import * 

... 

class LinkedList(Structure): 
    pass 

LinkedList._fields_ = [("data",c_void_p), ("next", POINTER(LinkedList))] 

... 

IedConnection_getServerDirectory=dlllib.IedConnection_getServerDirectory 
IedConnection_getServerDirectory.argtypes=[c_void_p, c_void_p] 
IedConnection_getServerDirectory.restype = c_int 
LogicalDevicesPtr = IedConnection_getServerDirectory(IedConnection,iedClientError) 

Параметр IedConnection извлекается другой функции как указатель, и я уверен, что он работает нормально. Также я вижу, что сама функция отлично работает (она инициирует коммуникации, которые можно увидеть в Wireshark).

Тогда я стараюсь, чтобы получить информацию в качестве результата функции:

LogicalDevicesList_p = cast(LogicalDevicesPtr,POINTER(LinkedList)) 

LogicalDeviceList = LogicalDevicesList_p.contents 

Эти линии проходит и следующая строка не удается:

Rdata = LogicalDeviceList.data 

с "вина Сегментация: 11"

Я предполагаю проблему, если с определениями типов, но я понятия не имею, где ошибка. Может ли кто-нибудь помочь?

+0

Почему вы определения вашего Python 'LinkedList', чтобы соответствовать C' STRUCT sLinkedList' вместо C ' LinkedList'? – user2357112

+1

И почему вы установили 'argtypes' и' restype' функции на стороне Python в нечто совершенно непохожее на то, как функция C фактически определена? – user2357112

ответ

2

Ну, похоже, я уже решил это сам:

IedConnection_getServerDirectory.restype = c_int 

неправильно и должно было изменено на:

IedConnection_getServerDirectory.restype = c_void_p 

И он начал работать нормально уже.

Но кроме того, я добавил третий аргумент и вызов функции, чтобы сделать его более аккуратным:

IedConnection_getServerDirectory.argtypes=[c_void_p, c_void_p, c_bool] 
LogicalDevicesPtr = IedConnection_getServerDirectory(IedConnection,iedClientError,c_bool(False)) 
Смежные вопросы