python setup.py build_ext --inplace
#cython: language_level=3
from cpython.pycapsule cimport PyCapsule_New, PyCapsule_IsValid, PyCapsule_GetPointer
class Test:
def __init__(self):
cdef int test = 10
cdef const char *name = "test"
self.vars = PyCapsule_New(<void *>&test, name, NULL)
# Print pointer address
print("{0:x}".format(<unsigned long long>test))
def peek(self):
cdef const char *name = "test"
if not PyCapsule_IsValid(self.vars, name):
raise ValueError("invalid pointer to parameters")
cdef int *test = <int *>PyCapsule_GetPointer(self.vars, name)
print(test[0])
# Print pointer address
print("{0:x}".format(<unsigned long long>test))
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("CythonTest.pyx"))
from CythonTest import Test
test = Test()
print(test.vars)
test.peek()
cbde7ebe70
<capsule object "test" at 0x0000027516467930>
0
cbde7ebe70
test
is a local variable (in C) so does not exist beyond the end of the __init__
function, and therefore when you try to access it again in peek
the memory has already been used for something else.
You can allocate memory for test
of the heap instead, so that the variable persists as long as you need (you need to create a destructor to deallocate it though).
from libc.stdlib cimport malloc, free
# destructor
cdef void free_ptr(object cap):
# This should probably have some error checking in
# or at very least clear any errors raised once it's done
free(PyCapsule_GetPointer(cap,PyCapsule_GetName(cap)))
class Test:
def __init__(self):
cdef int* test = malloc(sizeof(int))
test[0] = 10
cdef const char *name = "test"
self.vars = PyCapsule_New(<void *>&test, name, &free_ptr)
# etc