Note: This is a follow up to [SO]: How to pass a 2d array from Python to C?.
One way would be going through the following states:
CTypes pointer
Python lists
NumPy array
2 observations automatically arise:
It's very inefficient, but unfortunately I'm not aware how to get rid of #2. (which is the culprit)
The pointer holds information about the base type, but not about the dimension(s) of the array it was created from, so you have to "save" them, as you'll need them when "deconstructing" the pointer
code00.py:
#!/usr/bin/env python3
import ctypes as ct
import sys
import numpy as np
def main(*argv):
dim0 = 3
dim1 = 4
arr0 = np.empty([dim0, dim1], dtype=np.uint8)
print("Initial array:\n{0:}".format(arr0))
UI8Ptr = ct.POINTER(ct.c_uint8)
UI8PtrPtr = ct.POINTER(UI8Ptr)
ct_arr = np.ctypeslib.as_ctypes(arr0)
UI8PtrArr = UI8Ptr * ct_arr._length_
ct_ptr = ct.cast(UI8PtrArr(*(ct.cast(row, UI8Ptr) for row in ct_arr)), UI8PtrPtr)
arr1 = np.array([[ct_ptr[i][j] for j in range(dim1)] for i in range(dim0)], dtype=ct_ptr._type_._type_._type_)
print("\nFinal array:\n{0:}".format(arr1))
print("\nEqual arrays: {0:}".format(np.array_equal(arr0, arr1)))
if __name__ == "__main__":
print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
64 if sys.maxsize > 0x100000000 else 32, sys.platform))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)
Output:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058781199]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 064bit on win32
Initial array:
[[ 96 100 101 115]
[105 114 101 100]
[ 96 96 32 115]]
Final array:
[[ 96 100 101 115]
[105 114 101 100]
[ 96 96 32 115]]
Equal arrays: True
Done.
Fore more info on this topic check [SO]: Numpy error when converting array of ctypes types to void pointer (@CristiFati's answer).