Skip to content
Advertisement

ndpointer in ctypes structure field

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

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement