I cannot figure out how to use numpy.ndpointer as a field in a python ctypes structure. Here is some basic code, showing how I can do this without using ndpointer, but I would like to know if it’s possible to use ndpointer as well if it’s possible!
import numpy as np import ctypes class MyStruct_Working(ctypes.Structure): _fields_ = [ ('a', ctypes.c_ssize_t), ('values', ctypes.POINTER(ctypes.c_double))] def __init__(self, a, values): self.a = a self.values = values.ctypes.data_as(ctypes.POINTER(ctypes.c_double)) class MyStruct_NotWorking(ctypes.Structure): _fields_ = [ ('a', ctypes.c_ssize_t), ('values', np.ctypeslib.ndpointer(dtype=float, flags='C_CONTIGUOUS'))] def __init__(self, a, values): self.a = a self.values = values
Using the above code this works fine
m0 = MyStruct_Working(1, np.array([1,2,3]))
But when I call this, I get the following error message
m1 = MyStruct_NotWorking(1, np.array([1,2,3]))
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-19-8435d2743b55> in <module> ----> 1 m1 = MyStruct_NotWorking(1, np.array([1,2,3])) <ipython-input-17-beb0591858e6> in __init__(self, a, values) 17 def __init__(self, a, values): 18 self.a = a ---> 19 self.values = values TypeError: cannot be converted to pointer
Advertisement
Answer
Listing [Python.Docs]: ctypes – A foreign function library for Python.
According to [NumPy]: numpy.ctypeslib.ndpointer(dtype=None, ndim=None, shape=None, flags=None) (emphasis is mine):
An ndpointer instance is used to describe an ndarray in restypes and argtypes specifications.
argtypes and restype only have meaning in the context of a function (call), and that is when ndpointer should be used (exemplified in the URL).
As a workaround, you can have an ndpointer structure member, but you have to initialize it in the same manner as the ctypes.POINTER one (in MyStruct_Working). However, bear in mind that this will come with some limitations (you won’t have indexing) afterwards.
My suggestion is to stick with ctypes.POINTER(ctypes.c_double).