I am experimenting with the use of the ctypes package in Python. Currently attempting to pass a 3d NumPy array to a C function that takes a triple pointer as an argument and updates the values of the elements of the array. The C function is:
void effect_array(int ***ptr, int rows, int cols, int depth)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
for(int k = 0; k < depth; k++)
{
ptr[i][j][k] *= 2;
}
}
}
}
Currently, I have tried:
import ctypes as ct
import numpy as np
arr = np.array([
[
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]
],
[
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24]
]
])
arr_c = np.ascontiguousarray(arr)
lib = ct.CDLL("path/to/share_object.so")
_effect_array = lib.effect_array
_effect_array.argtypes = [ct.POINTER(ct.POINTER(ct.POINTER(ct.c_int))), ct.c_int, ct.c_int, ct.c_int]
_effect_array.restype = None
rows, cols, depth = arr.shape
t_ptr = (ct.POINTER(ct.POINTER(ct.c_int)) * rows)()
for i in range(rows):
t_ptr[i] = (ct.POINTER(ct.c_int) * cols)()
for j in range(cols):
t_ptr[i][j] = arr_c[i][j].ctypes.data_as(ct.POINTER(ct.c_int))
print("Original array =")
print(arr_c)
print()
_effect_array(t_ptr, rows, cols, depth)
print("Array after pass to function =")
print(arr_c)
This has resulted in an output of:
Original array =
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]
Array after pass to function =
[[[ 2 4 3 4]
[10 12 7 8]
[18 20 11 12]]
[[26 28 15 16]
[34 36 19 20]
[42 44 23 24]]]
What I would like to happen would be:
Original array =
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
[[13 14 15 16]
[17 18 19 20]
[21 22 23 24]]]
Array after pass to function =
[[[ 2 4 6 8]
[10 12 14 16]
[18 20 22 24]]
[[26 28 30 32]
[34 36 38 40]
[42 44 46 48]]]
I am not sure why the C function is not able to access the elements beyond the first two in a row. My understanding is that my current attempt is provided access to the start of the array and that it should be able to iterate through the rest of the array as can be done in this C example:
#include <stdio.h>
#include <stdlib.h>
void effect_array(int ***ptr, int rows, int cols, int depth)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
for(int k = 0; k < depth; k++)
{
ptr[i][j][k] *= 2;
}
}
}
}
int main()
{
int arr[2][2][2] = {
{
{1,2},
{3,4}
},
{
{5,6},
{7,8}
}
};
int arr2[5];
int *p = arr2;
int ***ptr = (int ***)malloc(2 * sizeof(int **));
for(int i = 0; i < 2; i++)
{
ptr[i] = (int **)malloc(2 * sizeof(int *));
for(int j = 0; j < 2; j++)
{
ptr[i][j] = &arr[i][j][0];
}
}
printf("Print array before:\n");
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
for(int k = 0; k < 2; k++)
{
printf("%d ", arr[i][j][k]);
}
printf("\n");
}
printf("\n");
}
effect_array(ptr, 2, 2, 2);
printf("Print array after:\n");
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
for(int k = 0; k < 2; k++)
{
printf("%d ", arr[i][j][k]);
}
printf("\n");
}
printf("\n");
}
for(int i = 0; i < 2; i++) free(ptr[i]);
free(ptr);
return 0;
}
This is also based off the discussion on a previous question I asked, credit to @SR143 for the working C example.
Any and all help is greatly appreciated.
t_ptr[i] = (ct.POINTER(ct.c_int) * cols)()andt_ptr[i][j] = arr_c[i][j].ctypes.data_as(ct.POINTER(ct.c_int))both discard the only remaining reference to the new array.