#python #arrays #c #numpy #ctypes
Вопрос:
Хороший день,
Я новичок в C и ctypes в Python.
Я пытаюсь передать функцию C в код Python.
Я продолжаю получать следующую ошибку: «чтение с нарушением доступа 0x0…» при чтении 2D-массивов («St» формы 10 000 x 521 и «dZ» формы 10 000 x 520) в следующей функции C:
#include lt;math.hgt; #include lt;stdio.hgt; double change (double * dZ, double * St, size_t lenTaus, size_t lenSims) { size_t i, j; double a, b; for (i = 0; i lt; lenSims; i ) /*Iterate through simulations.*/ { for (j = 0; j lt; (lenTaus - 1); j ) /*Iterate through taus.*/ { a = St[lenTaus * i j]; b = dZ[lenTaus * i j]; } } return 0.0; }
Переменные «lenSims» и «lenTaus» равны 10 000 и 521 соответственно.
Код Python для вызова функции C является:
import ctypes impor t numpy as np cCode = ctypes.CDLL("cCode_e.so") ### Read the C code in a form of shared library. cCode.change.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.c_size_t, ctypes.c_size_t] ### Let know what kind of input we provide to the C function. cCode.change.restype = ctypes.c_double ### Let know what kind of output we expect from the C function. St_Python = np.zeros([10000,521]) dZ_Python = np.random.randn(10000,520) St = St_Python.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) ### Convert a numpy array into a pointer to an array of doubles. dZ = dZ_Python.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) ### Convert a numpy array into a pointer to an array of doubles. lenTaus = St_Python.shape[1] ### Find the number of columns in the original array. lenSims = St_Python.shape[0] ### Find the number of rows in the original array. out = cCode.change(dZ, St, lenTaus, lenSims) ### Call the C function
Если я правильно понимаю проблему, я неправильно работаю с памятью при передаче целых массивов в качестве указателей на функцию C. Но я не знаю, как правильно их передать.
Могу я попросить вас о помощи?
С уважением,
Евгений
Комментарии:
1. как вы создаете
St_Python
иdZ_Python
обрабатываете массивы? Может быть, в одном из них недостаточно данных?2. Способ обработки массивов кажется неправильным. Если один из них равен 10000X521 (10000 строк и 521 столбец), 1-й индекс, который должен быть пройден, равен 10000 ( lenTaus ). Также 520 соответствует lenSims — 1 . Переключатель
lenSims
с(lenTaus - 1)
2 петлями. и индексация должна быть[lenSims * i j]
.3. Здравствуйте, я добавил определение массивов «St_Python» и «dZ_Python» в Python.
4. устраняет ли
dZ_Python = np.random.randn(10000,520)
-gt; gt;dZ_Python = np.random.randn(10000,521)
проблему?5. Кроме того, почему вы жестко закодировали значения в Python при создании массивов вместо использования
St_Python.shape[]
? Может быть, они отличаются друг от друга.
Ответ №1:
Похоже, что проблема вызвана переполнением буфера.
Предполагая, что массивы определены как:
St_Python = np.zeros([10000,521]) dZ_Python = np.random.randn(10000,520)
В функции C параметры lenTaus
и LenSims
являются 521
и 10000
соответственно. В результате конечное смещение, при котором dZ
осуществляется доступ, равно:
lenTaus * i j = lenTaus * (lenSims-1) (lenTaus - 1 - 1) = 521*9999 521-1-1 = 5209998
Размер dz
— это 10000 * 520
то 5200000
, что меньше конечного смещения, поэтому происходит переполнение буфера и вызывается неопределенное поведение.
Одним из решений является изменение расчетов смещения для dZ
:
b = dZ[(lenTaus - 1) * i j];