Мутировать целочисленный массив, используя ctypes - PullRequest
4 голосов
/ 25 августа 2009

В настоящее время я нахожусь в процессе перемещения узкого места производительности в моем коде python в c, чтобы исследовать эффекты производительности. Этот код запустит симуляцию и сообщит результаты в python через ctypes. Однако у меня возникают проблемы с корректным совпадением типов.

Несмотря на то, что я пытаюсь решить эту конкретную проблему, я также ищу более общие рекомендации по работе с ctypes, так как документация и процедура кажутся немного тонкими.

У меня есть следующая функция c:

extern "C" {
    void f( int* array, int arraylen ) {
        for(int i = 0; i < arraylen; i++) {
            array[i] = g() // mutate the value array[i];
        }
    }
}

И следующий код на python:

import ctypes

plib   = ctypes.cdll.LoadLibrary('./mylib.so')
_f = plib.f
_f.restype  = None
_f.argtypes = [ ctypes.POINTER(ctypes.c_int), ctypes.c_int ]
seqlen = 50
buffer = ctypes.c_int * seqlen
_f( buffer, seqlen )

Однако этот фрагмент умирает со следующей трассировкой:

Traceback (most recent call last):
  File "particle.py", line 9, in <module>
    _f( buffer, seqlen )
ctypes.ArgumentError: argument 1: <type 'exceptions.TypeError'>: expected LP_c_int instance instead of _ctypes.ArrayType

1 Ответ

4 голосов
/ 25 августа 2009

Похоже, что вы хотите функция приведения :

Функция приведения может использоваться для приведения экземпляра ctypes в указатель на другой тип данных ctypes.Метод cast принимает два параметра: объект ctypes, который является или может быть преобразован в некоторый указатель, и тип указателя ctypes.Он возвращает экземпляр второго аргумента, который ссылается на тот же блок памяти, что и первый аргумент:

>>> a = (c_byte * 4)()
>>> a
<__main__.c_byte_Array_4 object at 0xb7da2df4>
>>> cast(a, POINTER(c_int))
<ctypes.LP_c_long object at ...>
>>>
...