Python, использующий ctypes для работы с аргументом OUT

1

В файле заголовка dll у меня есть следующая структура

typedef struct USMC_Devices_st{
DWORD NOD;          // Number of the devices ready to work

char **Serial;      // Array of 16 byte ASCII strings
char **Version;     // Array of 4 byte ASCII strings
} USMC_Devices;         // Structure representing connected devices

Я бы хотел вызвать функцию dll: DWORD USMC_Init (USMC_Devices & Str);

Я попытался с этим:

class USMCDevices(Structure):
   _fields_ = [("NOD", c_long),
            ("Serial", c_char_p),
            ("Version", c_char_p)]

usmc = cdll.USMCDLL #this is the dll file
init = usmc.USMC_Init
init.restype = c_int32; # return type
init.argtypes = [USMCDevices]; # argument
dev = USMCDevices()
init(dev)

Я получаю сообщение об ошибке здесь. Я думаю, проблема связана с "Serial" и "Version", которые представляют собой массив, соответствующий NOD (количество устройств).

Любые идеи, как решить эту проблему?

Я очень ценю вашу помощь!!!

Теги:
dll
ctypes

1 ответ

2
Лучший ответ

Используйте POINTER(c_char_p) для указателей char **. Индексирование Serial или Version создает строку Python для указанной строки с нулевым завершением. Обратите внимание, что индексирование в массиве за пределами NOD - 1 либо приводит к значениям мусора, либо приводит к сбою интерпретатора.

C:

#include <windows.h>

typedef struct USMC_Devices_st {
    DWORD NOD;       // Number of the devices ready to work
    char **Serial;   // Array of 16 byte ASCII strings
    char **Version;  // Array of 4 byte ASCII strings
} USMC_Devices;

char *Serial[] = {"000000000000001", "000000000000002"};
char *Version[] = {"001", "002"};

__declspec(dllexport) DWORD USMC_Init(USMC_Devices *devices) {

    devices->NOD = 2;
    devices->Serial = Serial;
    devices->Version = Version;

    return 0;
}

// build: cl usmcdll.c /LD

Python:

import ctypes
from ctypes import wintypes

class USMCDevices(ctypes.Structure):
    _fields_ = [("NOD", wintypes.DWORD),
                ("Serial", ctypes.POINTER(ctypes.c_char_p)),
                ("Version", ctypes.POINTER(ctypes.c_char_p))]

usmc = ctypes.cdll.USMCDLL
init = usmc.USMC_Init
init.restype = wintypes.DWORD
init.argtypes = [ctypes.POINTER(USMCDevices)]
dev = USMCDevices()
init(ctypes.byref(dev))

devices = [dev.Serial[i] + b':' + dev.Version[i]
           for i in range(dev.NOD)]
print('\n'.join(d.decode('ascii') for d in devices))

Вывод:

000000000000001:001
000000000000002:002
  • 0
    Огромное спасибо!!! Вы мне очень помогли !! Тем не менее, у меня все еще есть проблема. Указатель dev.Serial [i] .value не указывает на правильное местоположение. Например: я получаю правильную последовательную строку в dev.Serial [2] .value, в то время как при индексе i = 0 или i = 1 я получаю неверные данные (размер массива только два). Есть идеи???
  • 0
    Дополнительно: если я изменяю Структуру на и определяю сначала Версия, а затем Последовательный, то строка будет иметь вид dev.Serial [1], а все остальные индексы дают неверные результаты. Буду очень признателен за подсказку!
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню