如何通过Python / C API将Python实例传递给C ++ [英] How to pass Python instance to C++ via Python/C API

查看:216
本文介绍了如何通过Python / C API将Python实例传递给C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Python(2.7)扩展我的库,通过包装SWIG 2.0的接口,并有一个图形对象,其中我想创建一个访问者。在C ++中,界面如下所示:

I'm extending my library with Python (2.7) by wrapping interfaces with SWIG 2.0, and have a graph object in which I want to create a visitor. In C++, the interface looks like this:

    struct Visitor
    {
        virtual void OnStateBegin() = 0;
        virtual void OnNode(Node* n) = 0;
        virtual void OnStateEnd() = 0;
    };

我想在Python中定义一个类,它在python中定义,允许定义访问者:

I would like to define a class in Python that does the equivalent, all defined in python, that will allow for the definition of a 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)

我要做的是创建一个python脚本中的GraphVisitor实例,并为C ++中给定的实例调用OnStateBegin(),OnNode()和OnStateEnd()方法。这里是我想在Python做的:

And what I'm trying to do is create an instance of a GraphVisitor in python script, and call the methods OnStateBegin(), OnNode(), and OnStateEnd() for a given instance from C++. Here's what I'd like to do in 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++?

在我的Swift包装的C ++中,我不知道如何获取实例mvis '?我可以调用在Python中定义的函数没有问题,但是实例让我陷入困境!

And in my C++ wrapped by Swig, I'm not sure how to get at the instance 'mvis'? I can call functions defined in Python no problem, but instances has me stumped!

推荐答案

为了解决这个问题,模块中的类给出了它的模块名和类名(以下代码假定模块尚未加载):

In order to solve this problem, I retrieved the class from the module given it's module name and class name (the code below assumes the module hasn't already 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 I had the module, I looked up the class from 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);

我通过在C ++中实例化python类来简化我的问题,然后创建我的访问者访问它:

I simplified my problem a bit by instantiating the python class in C++, then created my visitor, and finally 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);
            }
        }
    }
}

visitor有3个函数OnStateBegin(),OnNode()和OnStateEnd()。我添加到我的SWIG python绑定生成器一个选项生成头文件,用于外部访问SWIG运行时与 - 外部运行时选项,所以我可以在C + +(INode *下面)创建一个类,并将其传递给Python作为参数python OnNode函数如下(为简洁而删除错误检查):

The visitor had 3 functions OnStateBegin(), OnNode(), and OnStateEnd(). I added to my SWIG python binding generator an option to generate a header file for external access to the SWIG runtime with the -external-runtime option, so I could create a class in C++ (INode* below) and pass it to Python as the argument to the python OnNode() member function as follows (error checking removed for 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));
}

这篇关于如何通过Python / C API将Python实例传递给C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆