Using data in Python code from C++ using Cython -
i'm trying list c++ code in python code using cython.
here header (ex.h):
namespace c { class c { int id; public: c(int id) { this->id = id; } int getid(); }; typedef std::vector<c> clist; }
and source file (ex.cpp):
namespace c { int c::getid() { return this->id; } clist getlist(int t) { clist list; (int = 0; < t; ++i) { c c(i); list.push_back(c); } return list; } }
so in python code want iterate through clist this:
import exapi in exapi.take_list(): print # or print i.get_id()
in .pyx file (exapi.pyx) i'm trying create cython extension handle c++ object:
cdef extern "ex.h" namespace "c": cdef cppclass c: c(int) except + int getid() cdef cppclass clist: pass cdef clist getlist(int) cdef class py_c: pass cdef class py_clist: pass def take_list(): return getlist(10) # know wrong
what forwarding methods , function should add py_c , py_clist make python code working?
and read using c++ in cython, there new objects creates in cython code, in case need use objects created in c++ side.
when trying work out rewrote of example, in principle there's no difference between gave , i'm giving back.
i changed names, too, because example ones short me ;).
cobject.hpp
#include <vector> namespace cobject { class cobject { int id; public: cobject(int id): id(id) {} int getid(); }; typedef std::vector<cobject> cobjectlist; cobjectlist getlist(int t); }
cobject.cpp
#include "cobject.hpp" namespace cobject { int cobject::getid() { return this->id; } cobjectlist getlist(int t) { cobjectlist list; (int = 0; < t; ++i) { list.push_back(cobject(i)); } return list; } }
these aren't different.
i wanted use pyximport
, use c++ need special file:
cobject_api.pyxbld
import os distutils.extension import extension dirname = os.path.dirname(__file__) def make_ext(modname, pyxfilename): return extension( name=modname, sources=[pyxfilename, "cobject.cpp"], language="c++", include_dirs=[dirname] )
and magic:
cython_api.pyx
from cython.operator cimport dereference deref cdef extern "cobject.hpp" namespace "cobject": cdef cppclass cobject: cobject(int) except + int getid() cdef cppclass cobjectlist: cobject &at(size_t) size_t size() cdef cobjectlist getlist(int) # cython wrappers cdef class pycobject: cdef cobject *wrapped cdef object keepalive def __cinit__(self, keepalive): self.keepalive = keepalive property id: def __get__(self): return self.wrapped.getid() def __repr__(self): return "pycobject({})".format(self.id) cdef class pycobjectlist: cdef cobjectlist wrapped def __iter__(self): cdef pycobject pycobject cdef size_t idx = 0 while idx < self.wrapped.size(): pycobject = pycobject(self) pycobject.wrapped = &self.wrapped.at(idx) yield pycobject idx += 1 def take_list(): cdef pycobjectlist pycobjectlist = pycobjectlist() pycobjectlist.wrapped = getlist(10) return pycobjectlist
which run like:
main.py
import pyximport pyximport.install() import cobject_api in cobject_api.take_list(): print("{} has id {}".format(i, i.id))
the idea wrapper classes take ownership of data. since getlist
returning value have copy around, other object wrapper can use pointer.
rather using cobjectlist
type, might make more sense use pre-wrapped vector class , iterate on that. however, unless keep on heap pointers indirection it's not going nice wrap them.
this because can't point things keep on stack, , cython requires pointing things if wants tie in python's garbage collector. explains keepalive
variable in code for: unlike in python deleting vector doesn't affect elements, in c++ trashes them completely. vector of pointers, these problems can alleviated.
also see link on question. of same points have been made, , architechture more traditional setup given.
Comments
Post a Comment