Как получить доступ к указателю на значения указателя в python?

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

Итак, если я правильно понял вашу проблему, вам следует:

  1. Используйте pointer вместо int32 типа
  2. Доступ к содержимому указателя (также известному как разыменование указателя) осуществляется через 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 я надеялся на более читаемую информацию :)?