How to pass Python instance to C++ via Python/C API -
i'm extending library python (2.7) wrapping interfaces swig 2.0, , have graph object in want create visitor. in c++, interface looks this:
struct visitor { virtual void onstatebegin() = 0; virtual void onnode(node* n) = 0; virtual void onstateend() = 0; }; i define class in python equivalent, defined in python, allow definition of visitor:
class graphvisitor: def __init__(self, label): self._label = label print("__init__(self,{0})".format(self._label)) def onstatebegin(self): print("onstatebegin()" + self._label) def onnode(self, i_node): print("onnode()" + self._label) def onstateend(self): print("onstateend()" + self._label) and i'm trying create instance of graphvisitor in python script, , call methods onstatebegin(), onnode(), , onstateend() given instance c++. here's i'd in python:
#model swig wrapped class mvis = graphvisitor("this test") model.visit("mvis") # i'm not sure how pass instance 'mvis' c++? and in c++ wrapped swig, i'm not sure how @ instance 'mvis'? can call functions defined in python no problem, instances has me stumped!
in order solve problem, retrieved class module given it's module name , class name (the code below assumes module hasn't been loaded):
void model::visit(const char* mod_name, const char* class_name) { pyerr_clear(); pyobject* mod_name_obj = pystring_fromstring(mod_name); pyobject* class_name_obj = pystring_fromstring(class_name); pyobject* py_module = pyimport_import(mod_name_obj); pyobject* err_1 = pyerr_occurred(); if(err_1) pyerr_print(); once had module, looked class it's dictionary:
if(py_module) { pyobject* py_module_dict = pymodule_getdict(py_module); pyobject* py_class = pydict_getitem(py_module_dict, class_name_obj); i simplified problem bit instantiating python class in c++, created visitor, , visited it:
if(py_class && pyclass_check(py_class) && pycallable_check(py_class)) { pyobject* inst = pyinstance_new(py_class, 0, 0); if(inst && pyinstance_check(inst)) { imodel::ivisitorptr py_visitor = new pymodelvisitor(inst); _model->visit(py_visitor); } } } } the visitor had 3 functions onstatebegin(), onnode(), , onstateend(). added swig python binding generator option generate header file external access swig runtime -external-runtime option, create class in c++ (inode* below) , pass python argument python onnode() member function follows (error checking removed brevity):
visitorctrl onnode(inode* node) { node* node_impl = new nodeimpl(node); pyobject* pynode = swig_newpointerobj(node_impl, swig_typequery("node *"), 0); pyobject* result = pyobject_callmethodobjargs(_inst, pystring_fromstring("onnode"), pynode, 0); long rivis = pyint_aslong(result); return(static_cast<visitorctrl>(rivis)); }
Comments
Post a Comment