I would like to port an existing c++ library with cython to Python, with the C++ library employing templates. In this case, it is the adevs library.
The question is how can I store Python objects in a C++ container with Cython? I know this is somehow discouraged, for issues of reference counting, but can it be done nevertheless and if so, how?
I am aware of Gauthier Boaglios' answer to a similar question. However, this does not address the issue of reference counting, apparently, as I tried the following:
Let's say in 'cadevs.pxd' I have the following code:
cdef extern from "adevs/adevs_digraph.h" namespace "adevs":
cdef cppclass PortValue[VALUE, PORT]:
PortValue() except +
PortValue(PORT port, const VALUE& value) except +
PORT port
VALUE value
And in 'adevs.pyx':
from cpython.ref cimport PyObject
cimport cadevs
ctypedef PyObject* PythonObject
cdef class PortValue:
cdef cadevs.PortValue[PythonObject, PythonObject]* _c_portvalue
def __cinit__(self, object port, object value):
self._c_portvalue = new cadevs.PortValue[PythonObject, PythonObject](
<PyObject *>port, <PyObject *>value
)
def __dealloc__(self):
del self._c_portvalue
property port:
def __get__(self):
return <object>self._c_portvalue.port
property value:
def __get__(self):
return <object>self._c_portvalue.value
Then I cythonize and compile
$ cython --cplus -3 adevs.pyx
$ g++ -shared -pthread -fPIC -fwrapv -O2 -Wall -I/usr/include/python3.4m -I../include -lpython3.4m -o adevs.so adevs.cpp
But running in python or ipython
import adevs
pv = adevs.PortValue((1,2), 3)
pv.port
pv.port
crashes Python as the reference to the (1, 2) tuple is lost, apparently.
boost::python
that provides far better and straight forward integration of c++ than the raw python c-API. – Prepositive