#python #pointers #ctypes
#python #указатели #ctypes
Вопрос:
У меня есть это объявление указателя python:
numberOfThings = ctypes.c_int32()
indexes = ctypes.c_int32()
Если я напечатаю значения:
print numberOfThings.value
print indexes.value
Я получил:
0
0
Я выполняю вызов функции:
the_Dll.doSomeThing(ctypes.byref(numberOfThings), ctypes.byref(indexes))
Если я сейчас напечатаю значения:
print "numberOfThings values", numberOfThings.value
print "indexes values", indexes.value
Я получил:
numberOfThings values 3
indexes values 147107816
Индексы — это указатель на указатель, но как мне получить значение индексов? Моя цель — перебрать nr numberOfThings и для каждого numberOfThings вывести значение индексов, подобное этому:
for i in range(numberOfThings.value):
print 'Value of indexes', how to access indexes real value?
Кто-нибудь знает, как это решить? Спасибо!
Комментарии:
1. Каков вариант использования, когда требуется что-то подобное или добавляет ясности? С удовольствием почитаю дальше.
2. Я обращаюсь к функции в файле DLL. Эта функция проверит количество шин, подключенных к компьютеру, и описание шин.
Ответ №1:
Из официальной документации python:
Экземпляры указателя создаются путем вызова функции pointer() для типа ctypes:
>>>
>>> from ctypes import *
>>> i = c_int(42)
>>> pi = pointer(i)
>>>
Экземпляры указателя имеют атрибут contents, который возвращает объект, на который указывает указатель, объект i выше:
>>>
>>> pi.contents
c_int(42)
>>>
Итак, если я правильно понял вашу проблему, вам следует:
- Используйте
pointer
вместоint32
типа - Доступ к содержимому указателя (также известному как разыменование указателя) осуществляется через
variable.contents
атрибут.
Обновить
В продолжение наших последних комментариев, вот форматированная версия вашего возможного решения:
numberOfThings = ctypes.c_int32()
indexes = ctypes.c_void_p()
_Dll.doSomeThing(ctypes.byref(numberOfThings),ctypes.byref(indexes))
ptrt = ctypes.POINTER(ctypes.c_double*numberOfThings.value)
mydblPtr = cast(indexes, ctypes.POINTER(ctypes.c_double*numberOfThings.value))
indexes = ptrt(mydblPtr.contents)
for content in indices.contents:
print content
Комментарии:
1. Спасибо! Когда я пытаюсь получить доступ к содержимому указателя, я получаю
AttributeError: 'c_void_p' object has no attribute 'contents'
. Может быть, я забыл какой-то импорт ..? Разве этого недостаточно сfrom ctypes import *
?2. Вы должны привести
c_void_p
к правильному типу:mydblPtr = cast(myVoidVal, POINTER(c_double))
учитываяmyVoidVal
c_void_p
экземпляр иc_double
тип вашего указателя (типindexes
). В этом случаеmydblPtr
будет иметьcontents
атрибут.3. Если я правильно вас понимаю, могу ли я сделать это следующим образом?:
numberOfThings = ctypes.c_int32() indexes = ctypes.c_void_p() _Dll.doSomeThing(ctypes.byref(numberOfThings),ctypes.byref(indexes)) ptrt = ctypes.POINTER(ctypes.c_double*numberOfThings.value) mydblPtr = cast(indexes, POINTER(c_double)) indexes = ptrt(mydblPtr.contents)
В этом случае у меня будет следующий выводTypeError: expected c_double_Array_3 instead of c_double
для этой строки:indexes = ptrt(mydblPtr.contents)
Есть идеи :)?4. Попробуйте привести определение правильного типа массива, поэтому напишите
mydblPtr = cast(indexes, POINTER(c_double*numberOfThings.value))
5. (Я обновил свой ответ, чтобы сделать решение читаемым и доступным для всех :))
Ответ №2:
Я думаю, мы можем начать с создания указателя, а не int32:
numberOfThings = ctypes.c_int32()
indices = ctypes.c_void_p()
_Dll.doSomeThing(ctypes.byref(numberOfThings), ctypes.byref(indices))
Затем мы можем преобразовать адрес в правильно типизированный указатель на массив (здесь предполагается, что он удваивается):
ptrt = ctypes.POINTER(ctypes.c_double*numberOfThings.value)
indices = ptrt(indices.contents)
for n in indices.contents:
print n
Комментарии:
1. Спасибо за ответ! Я получил,
AttributeError: 'c_void_p' object has no attribute 'contents'
разве этого не должно быть достаточноfrom ctypes import *
для получения соединений?2. Моя ошибка, Алекс Гидан предоставил информацию о cast(). Попробуйте привести к ptrt вместо POINTER(c_double):
indices = ctypes.cast(indices, ptrt)
3.Спасибо!! Хорошо, теперь я могу выполнять цикл :)! Но все же значения, похоже, довольно сложно оценить 🙂 Код:
ptrt = ctypes.POINTER(ctypes.c_double*numberOfThings.value)
indexes = ctypes.cast(indexes, ptrt)
indexes = ptrt(indexes.contents)
print indexes
for n in indexes.contents:
print n
Это будет напечатано:<ctypes.LP_c_double_Array_3 object at 0x14490170>
2.12199579097e-314
4.37702459859e-299
-1.6068586969e-315
я надеялся на более читаемую информацию :)?