Проблемы с доступом к переменной, которая приводится в указатель на массив int с ctypes в Python - PullRequest
0 голосов
/ 19 августа 2010

У меня есть код C, который использует переменную data, которая представляет собой большой двумерный массив, созданный с помощью malloc с переменным размером. Теперь мне нужно написать интерфейс, чтобы функции C могли вызываться из Python. Для этого я использую ctypes.

код C:

FOO* pytrain(float **data){
    FOO *foo = foo_autoTrain((float (*)[])data);
    return foo;
}

с

FOO *foo_autoTrain(float data[nrows][ncols]) {...}

Код Python:

autofoo=cdll.LoadLibrary("./libfoo.so")
... data gets filled ...
foo = autofoo.pytrain(pointer(pointer(p_data)))

Моя проблема в том, что когда я пытаюсь получить доступ к data в foo_autoTrain, я получаю только 0.0 или другие случайные значения и ошибку сегмента позже. Так как же мне передать float (*)[])data в foo_autoTrain на Python?

Пожалуйста, не стесняйтесь указывать, если я описал какую-то часть своей проблемы, недостаточно достаточную.

1 Ответ

0 голосов
/ 09 сентября 2010

Мне кажется, что проблема заключается в неправильном понимании того, как многомерные массивы работают в C. Выражение типа a[r][c] может означать одно из двух в зависимости от типа a. Если бы тип a был float **, то выражение означало бы двойную разыменовку со смещением указателя, что-то вроде этого, если сделать длинную руку:

float *row = a[r]; // First dereference yields a pointer to the row array
return row[c]      // Second dereference yields the value

Если тип a был взамен float (*)[ncols], то выражение становится просто сокращением для формирования непрерывной одномерной области памяти в виде многомерного массива:

float *flat = (float *)a;
return flat[(r * ncols) + c]; // Same as a[r][c]

Таким образом, в вашем коде C тип аргумента pytrain() должен быть либо float *, либо float (*)[ncols], и ваш код Python должен выглядеть примерно так (если вы используете NumPy для данных массива) :

c_float_p = ctypes.POINTER(ctypes.c_float)
autofoo.pytrain.argtypes = [c_float_p]
data = numpy.array([[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]], dtype=numpy.float32)
data_p = data.ctypes.data_as(c_float_p)
autofoo.pytrain(data_p)

И если вы действительно используете NumPy, загляните на страницу ctypes вики SciPy .

...