카테고리 없음
[파이썬/Ctypes] numpy 2차원 배열을 C 함수로 넘기기
미친토끼
2021. 3. 11. 14:59
2차원 배열 합성곱에 사용될 수 있는 Scipy 함수인 correlate2d와 convolve2d에서 padding과 stride를 지원하지 않는 것 같아 직접 만들어볼까 싶어서 Ctypes에서 넘파이 부분을 뒤적거리고 있는데 생각보다 자료가 많지는 않다.
2차원 행렬의 경우, 현재까지 알아본 바론, 2차원 배열을 C로 넘길 수는 있지만, 수령하는 C쪽에서는 1차원 배열처럼 다룬다는 것이다. 그것을 돌려받은 파이썬 넘파이에서는 능청스럽게도 그것을 2차원 행렬로 여긴다는 것이다. C에서 1차원 배열을 2차원 행렬처럼 인덱싱하기가 번거롭고 복잡할 것 같다는 생각이 든다. 일단, 하나씩 익혀보자.
// numpy_1.c
// double형 배열과 그 shape를 인자로 받는다.
// 여기에서 인덱싱을 조금 낯설게, 'arr[i * width + j]'식으로 하고 있는데 풀어보면,
// for (int i=0; i < height+width; i++)
// arr[i] *= 2;
// 와 동일하다. 아무래도 1차원 배열이다 보니, 행렬처럼 인덱싱해야 할 필요가 있을 때 참고하면 될 것 같다.
void numpy_1(double * arr, int height, int width) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
arr[i * width + j] *= 2;
}
}
}
# numpy_1.py
import ctypes
import numpy as np
# float64임을 지정해서 C의 double형과 크기를 맞춘다.
x = np.arange(1., 13., dtype=np.float64)
x = x.reshape(3, 4)
height, width = x.shape # 3, 4
print(x)
print(height, width)
c_lib = ctypes.CDLL("./numpy_1.so")
# 매개변수 타입과 반환 자료형을 알려줘도 되고 안 해도 잘 작동하더라.
#c_lib.numpy_1.argtypes = [ctypes.POINTER(ctypes.c_double), ctypes.c_int, ctypes.c_int]
#c_lib.numpy_1.restype = None
# double 포인터 자료형을 만들어, 원본 자료의 shape과 함께 C 함수로 넘긴다.
array = x.ctypes.data_as(ctypes.POINTER(ctypes.c_double))
# C 함수에서는 array를 포인터로 받아 내부의 자료를 변경한다.
c_lib.numpy_1(array, height, width)
# 변경된 원본 데이터를 출력한다.
print(x)
[실행 결과]
[[ 1. 2. 3. 4.]
[ 5. 6. 7. 8.]
[ 9. 10. 11. 12.]]
3 4
[[ 2. 4. 6. 8.]
[10. 12. 14. 16.]
[18. 20. 22. 24.]]