如何将Python实例传递给C++;通过Python/capi
我正在用Python(2.7)扩展我的库,方法是用SWIG 2.0包装接口,并有一个图形对象,我想在其中创建一个访问者。在C++中,界面看起来像这样:如何将Python实例传递给C++;通过Python/capi,python,c++,python-2.7,swig,Python,C++,Python 2.7,Swig,我正在用Python(2.7)扩展我的库,方法是用SWIG 2.0包装接口,并有一个图形对象,我想在其中创建一个访问者。在C++中,界面看起来像这样: struct Visitor { virtual void OnStateBegin() = 0; virtual void OnNode(Node* n) = 0; virtual void OnStateEnd() = 0; }; 我想在Python中定义一个类,该类使
struct Visitor
{
virtual void OnStateBegin() = 0;
virtual void OnNode(Node* n) = 0;
virtual void OnStateEnd() = 0;
};
我想在Python中定义一个类,该类使用Python定义,可以定义访问者:
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)
我想做的是在Python脚本中创建一个GraveSuccor实例,并从C++调用给定实例的方法StATeEngEnter()、OnNoDeNe()和OnStAtEnEnter()。下面是我想用Python做的事情:
#model is a SWIG wrapped class
mvis = GraphVisitor("This is a test")
model.Visit("mvis") # I'm not sure how to pass the instance 'mvis' to C++?
和在我用SWIG包裹的C++中,我不知道如何在实例“MVIS”中得到?我可以毫无问题地调用Python中定义的函数,但实例让我难堪
我不知道用SWIG是否可以,但你可以用SWIG sip_向量_测试。h:class EXPORT Node {
public:
explicit Node(int n) : n_(n) {};
int getN() const { return n_; }
private:
int n_;
};
struct EXPORT NodeVisitor {
virtual void OnNode(Node* n) = 0;
};
struct EXPORT Graph {
public:
void addNode(int num);
void accept(NodeVisitor *nv);
private:
std::vector< std::shared_ptr<Node> > nodes_;
};
从Python中使用它:
>>> import pyvisit
>>> g = pyvisit.Graph()
>>> g.addNode(3)
>>> g.addNode(5)
>>> class PyNodeVisitor(pyvisit.NodeVisitor):
>>> def OnNode(self, node):
>>> print(node.getN())
>>> pnv = PyNodeVisitor()
>>> g.accept(pnv)
3
5
我在我的主页上放了一个包含此测试项目源代码的文件。为了解决此问题,我从模块中检索了给定模块名和类名的类(下面的代码假设模块尚未加载): 一旦我有了这个模块,我就从它的字典中查找这个类:
if(py_module)
{
PyObject* py_module_dict = PyModule_GetDict(py_module);
PyObject* py_class = PyDict_GetItem(py_module_dict, class_name_obj);
我通过在C++中实例化Python类来简化我的问题,然后创建了我的访问者,最后访问它:
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);
}
}
}
}
访问者有3个函数onStateBeagin()、OnNode()和OnStateEnd()。我添加到我的SpyPython绑定生成器中,生成一个用于访问SWIG运行时的头文件,用它,这样我就可以在C++中创建一个类(下面是iNoD*),并将它传递给Python作为Python OnNoDeNe()函数的参数(为简洁)删除错误:
VisitorCtrl OnNode(INode*node)
{
Node*Node_impl=新的NodeImpl(Node);
PyObject*pynode=SWIG_NewPointerObj(node_impl,SWIG_TypeQuery(“node*”),0);
PyObject*result=PyObject\u CallMethodObjArgs(\u inst,PyString\u FromString(“OnNode”),pynode,0);
长rivis=PyInt_AsLong(结果);
返回(静态_-cast(rivis));
}
mvis
只是python类的一个实例。它与您的struct访问者
没有任何关系。在C/C++中,您只能作为PyObject*
访问它。我知道这一点。我试图描述我在Python中定义访问者,那是C++对应的。你看到我以前的答案了吗?(你可以跳过关于嵌入的比特,但是从py物件转换到C++接口的一点点就做你想要的)Frimo——谢谢!你的东西真的很有用!谢谢你的回答!我没有使用SIP,我想看看这是否可以在不添加新类型的情况下完成。
if(py_module)
{
PyObject* py_module_dict = PyModule_GetDict(py_module);
PyObject* py_class = PyDict_GetItem(py_module_dict, class_name_obj);
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);
}
}
}
}
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));
}