如何创建从抽象 c++ 派生的类的 python 对象实例 班级?

发布于 2024-07-14 03:10:44 字数 2909 浏览 6 评论 0原文

这是我的代码:

// c++ (main.cpp)
#include <vector>
#include <iostream>
#include <boost/python.hpp>
#include <boost/python/enum.hpp>
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>

using namespace std;
using namespace boost;
using namespace boost::python;

class Base
{
public:
    Base(void) {}
virtual void f1(void) = 0;
virtual void f2(void) = 0;
};

class Stack
{
public:
Stack(void) {}
void push(Base *e)
{
    stack.push_back(e);
}
void pushPython(boost::python::object &o)
{
    Base &e = extract<Base &>(o) BOOST_EXTRACT_WORKAROUND;
    push(&e);
}
void test(void)
{
    for(std::vector<Base *>::iterator i = stack.begin(); i != stack.end(); i++)
    {
        (*i)->f1();
        (*i)->f2();
    }
}
private:
std::vector<Base *> stack;
};


class DerivedCPP : public Base
{
public:
DerivedCPP(void) {}
virtual void f1(void)
{
    std::cout << "DerivedCPP f1()" << std::endl;
}
virtual void f2(void)
{
    std::cout << "DerivedCPP f2()" << std::endl;
}
};

BOOST_PYTHON_MODULE(mytest)
{
boost::python::class_<Base,boost::noncopyable>("Base",boost::python::no_init)
    .def( "f1", &Base::f1)
    .def( "f2", &Base::f2)
    ;

boost::python::class_<DerivedCPP,bases<Base>>("DerivedCPP")
    .def( "f1", &DerivedCPP::f1)
    .def( "f2", &DerivedCPP::f2)
    ;

boost::python::class_<Stack>("Stack", boost::python::no_init)
    .def( "push", &Stack::pushPython)
    .def( "test", &Stack::test)
    ;
}

int main(int argc, char** argv)
{
PyImport_AppendInittab("mytest", &initmytest);
Py_Initialize();
boost::python::object main_module(( handle<>( borrowed( PyImport_AddModule( "__main__" )))));
boost::python::object main_namespace = main_module.attr("__dict__");
boost::python::object mytest( (handle<>(PyImport_ImportModule("mytest"))) );
main_namespace["mytest"] = mytest;
Stack *STACK = new Stack();
main_namespace["Stack"] = ptr(STACK);
Base *e = new DerivedCPP();
STACK->push(e);
STACK->test();
boost::python::object main = import("__main__");
boost::python::object global(main.attr("__dict__"));
boost::python::object result = exec_file("test.py", global, global);
Py_Finalize();
return 0;
}


# python (test.py)
print 'test.py'
print

class DerivedPython(mytest.Base):
def __init__(self):
    print "DerivedPython __init__()"
def f1(self):
    print "DerivedPython f1()"
def f2(self):
    print "DerivedPython f2()"

print 'DerivedPython()'
p = DerivedPython()
p.f1()
p.f2()

print 'mytest.DerivedCPP()'
c = mytest.DerivedCPP()
c.f1()
c.f2()

print 'Stack.push(c)'
Stack.push(c)
print 'OK'

print "Stack.test()"
Stack.test()

print 'Stack.push(p)'
Stack.push(p) # crash!
print 'OK'

print "Stack.test()"
Stack.test()

我想让 python 类从 C++ 抽象类派生,然后将此对象传递回 C++。 我应该如何做到这一点而不崩溃?

This is my code:

// c++ (main.cpp)
#include <vector>
#include <iostream>
#include <boost/python.hpp>
#include <boost/python/enum.hpp>
#include <boost/python/def.hpp>
#include <boost/python/module.hpp>

using namespace std;
using namespace boost;
using namespace boost::python;

class Base
{
public:
    Base(void) {}
virtual void f1(void) = 0;
virtual void f2(void) = 0;
};

class Stack
{
public:
Stack(void) {}
void push(Base *e)
{
    stack.push_back(e);
}
void pushPython(boost::python::object &o)
{
    Base &e = extract<Base &>(o) BOOST_EXTRACT_WORKAROUND;
    push(&e);
}
void test(void)
{
    for(std::vector<Base *>::iterator i = stack.begin(); i != stack.end(); i++)
    {
        (*i)->f1();
        (*i)->f2();
    }
}
private:
std::vector<Base *> stack;
};


class DerivedCPP : public Base
{
public:
DerivedCPP(void) {}
virtual void f1(void)
{
    std::cout << "DerivedCPP f1()" << std::endl;
}
virtual void f2(void)
{
    std::cout << "DerivedCPP f2()" << std::endl;
}
};

BOOST_PYTHON_MODULE(mytest)
{
boost::python::class_<Base,boost::noncopyable>("Base",boost::python::no_init)
    .def( "f1", &Base::f1)
    .def( "f2", &Base::f2)
    ;

boost::python::class_<DerivedCPP,bases<Base>>("DerivedCPP")
    .def( "f1", &DerivedCPP::f1)
    .def( "f2", &DerivedCPP::f2)
    ;

boost::python::class_<Stack>("Stack", boost::python::no_init)
    .def( "push", &Stack::pushPython)
    .def( "test", &Stack::test)
    ;
}

int main(int argc, char** argv)
{
PyImport_AppendInittab("mytest", &initmytest);
Py_Initialize();
boost::python::object main_module(( handle<>( borrowed( PyImport_AddModule( "__main__" )))));
boost::python::object main_namespace = main_module.attr("__dict__");
boost::python::object mytest( (handle<>(PyImport_ImportModule("mytest"))) );
main_namespace["mytest"] = mytest;
Stack *STACK = new Stack();
main_namespace["Stack"] = ptr(STACK);
Base *e = new DerivedCPP();
STACK->push(e);
STACK->test();
boost::python::object main = import("__main__");
boost::python::object global(main.attr("__dict__"));
boost::python::object result = exec_file("test.py", global, global);
Py_Finalize();
return 0;
}


# python (test.py)
print 'test.py'
print

class DerivedPython(mytest.Base):
def __init__(self):
    print "DerivedPython __init__()"
def f1(self):
    print "DerivedPython f1()"
def f2(self):
    print "DerivedPython f2()"

print 'DerivedPython()'
p = DerivedPython()
p.f1()
p.f2()

print 'mytest.DerivedCPP()'
c = mytest.DerivedCPP()
c.f1()
c.f2()

print 'Stack.push(c)'
Stack.push(c)
print 'OK'

print "Stack.test()"
Stack.test()

print 'Stack.push(p)'
Stack.push(p) # crash!
print 'OK'

print "Stack.test()"
Stack.test()

I want to make python class derived from c++ abstract class and then pass this object back to c++. How should I do that without crash?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

软甜啾 2024-07-21 03:10:44

这有点复杂,但并不困难。 阅读此页面< /a>,它应该为您提供所需的一切。

您需要像这样包装抽象类:

struct BaseWrap : Base, wrapper<Base>
{
    void f1()
    {
        this->get_override("f1")();
    }

    void f2()
    {
        this->get_override("f2")();
    }

};

然后您必须按如下方式公开 Base:

class_<BaseWrap, boost::noncopyable>("Base")
    .def("f1", pure_virtual(&Base::f1))
    .def("f2", pure_virtual(&Base::f2))
    ;

It's a little complicated, but not difficult. Read this page, it should give you everything you need.

You need to wrap the abstract class like this:

struct BaseWrap : Base, wrapper<Base>
{
    void f1()
    {
        this->get_override("f1")();
    }

    void f2()
    {
        this->get_override("f2")();
    }

};

Then you have to expose Base as follows:

class_<BaseWrap, boost::noncopyable>("Base")
    .def("f1", pure_virtual(&Base::f1))
    .def("f2", pure_virtual(&Base::f2))
    ;
暮色兮凉城 2024-07-21 03:10:44

您可能还想查看 Py++ 包。 它是一个用于解析 C++ 代码并为该代码生成 boost::python 包装器的实用程序。 我只尝试了一点,但它似乎可以处理自动创建基类包装器和类似的事情(根据文档,作者能够导出几个boost库并通过生成绑定来在Python中运行他们的测试套件py++)。

You might also want to check out the Py++ package. It's a utility used for parsing C++ code, and generating boost::python wrappers for that code. I've only tried it a little, but it seems to handle automatically creating base class wrappers and things like that (and according to the docs, the author was able to export several boost libraries and run their test suites in Python by generating bindings via Py++).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文