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).