Я очень надеюсь, что какой-нибудь эксперт по Python / Ctypes / C может мне помочь с этим, вероятно, это мой недостаток знаний о структуре ввода, чтобы правильно использовать Ctypes при использовании Python для взаимодействия с C библиотеки.
Цель: Мне нужно получить доступ к нескольким библиотечным функциям, загружающим DLL с помощью ctypes и взаимодействующим с ней. Идея работает нормально большую часть времени, но есть несколько функций, которые принимают перечисления в качестве параметров, и эти перечисления очень чувствительны, когда дело доходит до типа int. Вот пример подделки:
typedef enum led_property : uint8_t {
LED_OFF = 0
LED_POWER
}
int32_t configure_led(const led_property, const int32_t value)
Это вид перечисления, которое получают функции не только для uint8_t, но также для int32_t, int_64t и т. Д.
Из python рецепт, который я нашел в сети, мне удалось "адаптировать" python перечисления с типами ctypes:
class EnumerationTypeUInt8(type(c_uint8)):
def __new__(metacls, name, bases, dict):
if not "_members_" in dict:
_members_ = {}
for key, value in dict.items():
if not key.startswith("_"):
_members_[key] = value
dict["_members_"] = _members_
cls = type(c_uint8).__new__(metacls, name, bases, dict)
for key, value in cls._members_.items():
globals()[key] = value
return cls
def __contains__(self, value):
return value in self._members_.values()
def __repr__(self):
return "<Enumeration {}>".format(self.__name__)
def EnumerationUInt8(c_uint8):
__metaclass__ = EnumerationTypeUInt8
_members_ = {}
def __init__(self, value):
for k, v in self._members_.items():
if v == value:
self.name = k
break
else:
raise ValueError("No enumeration member with value {}".format(value))
c_uint8.__init__(self, value)
@classmethod
def from_param(cls, param):
if isinstance(param, EnumerationUInt8):
if param.__class__ != cls:
raise ValueError("Can not mix enumeration members")
else:
return param
else:
return cls(param)
def __repr__(self):
return "<member {}={} of {}".format(self.name, self.value, self.__class__)
Я загружаю библиотеку и украшаю ее функции следующим образом:
class LedProperty(EnumerationUInt8):
LED_OFF = c_uint8(0)
LED_POWER = c_uint8(1)
lib = "library.dll"
self._lib = CDLL(lib)
configure_led = self._lib.configure_led
configure_led.argtypes = [LedProperty, c_int32]
configre_led.restype = c_int32
Проблема в том, что я перепробовал все, что мог, и никогда не смог правильно вызвать эту функцию configure_led python, большую часть времени я получаю следующую ошибку:
ctypes.ArgumentError class 'ValueError' No enumeration member with value c_ubyte(1)
or
ctypes.ArgumentError class 'ValueError' No enumeration member with value 1
Это происходит, потому что я вижу при отладке, что «EnumerationUInt8» «self. members .items ()» всегда является пустым dict. Так что, вероятно, эти настраиваемые перечисления с типами ctypes неправильно загружают свои члены. Я всегда заканчиваю на "else: return cls (param)"
Пробовал:
configure_led(LedProperty.LED_POWER, 5)
configure_led(LedProperty.LED_POWER.value, 5)
configure_led(c_uint8(LedProperty.LED_POWER), 5)
... и так далее! Кажется, нет ничего правильного.
Кто-нибудь знает, как правильно объявлять перечисления с использованием типов cytpes, а затем использовать эти перечисления в качестве аргументов для функций?
Обс .: Сейчас я использую Python 3.8.3 Заранее спасибо!