美文网首页
基于boostpython,C++父类、子类同时导入Python

基于boostpython,C++父类、子类同时导入Python

作者: 万士辰 | 来源:发表于2020-06-19 15:11 被阅读0次

    需求背景

    项目实际优化中会将部分较为稳定的逻辑进行C++化,当逻辑较为复杂时难免出现使用面向对象的设计方案,但未来有可能出现「对C++逻辑进行扩展或修改,且不修改C++代码」

    需求抽象

    • C++中存在TestBase、TestCppSub两个类
    • TestCppSub继承于TestBase
    • 将TestBase、TestCppSub分别导入Python,并在Python中实例化、方法调用
    • 在Python中声明TestPySub1继承于TestBase、TestPySub2继承于TestCppSub

    C++代码:

    class TestBase
    {
    public:
        virtual void f() 
        {
            cout<<"cpp: call TestBase f"<<endl;
        }
    };
    
    class TestCppSub : public TestBase
    {
    public:
        void f() override
        {
            cout << "cpp: call TestCppSub f" << endl;
        }
        virtual void g()
        {
            cout << "cpp: call TestCppSub g" << endl;
        }
    };
    
    template <typename T>
    class TestBaseWrapper : public T, public wrapper<T>
    {
    public:
        void f() override
        {
            cout << "cpp: call TestBaseWrapper f" << endl;
            if (auto f = this->get_override("f"))
            {
                f();
                return;
            }
            this->T::f();
        }
    
        void py_f()
        {
            cout << "cpp: call TestBaseWrapper py_f" << endl;
            this->T::f();
        }
    };
    
    template <class W, class X1, class X2, class X3>
    void bind_test_base_to_py(class_<W, X1, X2, X3>& binder)
    {
        binder
            .def("f", &W::py_f)
            ;
    }
    
    template <typename T>
    class TestCppSubWrapper : public TestBaseWrapper<T>
    {
    public:
        void g() override
        {
            cout << "cpp: call TestCppSubWrapper g" << endl;
            if (auto g = this->get_override("g"))
            {
                g();
                return;
            }
            this->T::g();
        }
    
        void py_f()
        {
            cout << "cpp: call TestCppSubWrapper py_f" << endl;
            this->T::f();
        }
        void py_g()
        {
            cout << "cpp: call TestCppSubWrapper py_g" << endl;
            this->T::g();
        }
    };
    
    
    template <class W, class X1, class X2, class X3>
    void bind_test_cpp_sub_to_py(class_<W, X1, X2, X3>& binder)
    {
        bind_test_base_to_py<W>(binder);
        binder
            .def("g", &W::py_g)
            ;
    }
    
    void cpp_call_f(TestBase* obj)
    {
        obj->f();
    }
    void cpp_call_g(TestCppSub* obj)
    {
        obj->g();
    }
    
    auto test_base_binder = class_<TestBaseWrapper<TestBase>, boost::noncopyable>("TestBase", init<>());
    bind_test_base_to_py(test_base_binder);
    
    auto test_cpp_sub_binder = class_<TestCppSubWrapper<TestCppSub>, bases<TestBase>, boost::noncopyable>("TestCppSub", init<>());
    bind_test_cpp_sub_to_py(test_cpp_sub_binder);
    

    Python测试代码:

    TestBase().f()
    cpp_call_f(TestBase())
    

    cpp: call TestBaseWrapper py_f
    cpp: call TestBase f

    cpp: call TestBaseWrapper f
    cpp: call TestBase f

    print isinstance(TestCppSub(), TestBase)
    TestCppSub().f()
    cpp_call_f(TestCppSub())
    TestCppSub().g()
    cpp_call_g(TestCppSub())
    

    True

    cpp: call TestCppSubWrapper py_f
    cpp: call TestCppSub f

    cpp: call TestBaseWrapper f
    cpp: call TestCppSub f

    cpp: call TestCppSubWrapper py_g
    cpp: call TestCppSub g

    cpp: call TestCppSubWrapper g
    cpp: call TestCppSub g

    class TestPySub1(TestBase):
        def f(self):
            print "py: call TestPySub1 f"
    print isinstance(TestPySub1(), TestBase)
    TestPySub1().f()
    cpp_call_f(TestPySub1())
    

    True

    py: call TestPySub1 f

    cpp: call TestBaseWrapper f
    py: call TestPySub1 f

    class TestPySub2(TestCppSub):
        def f(self):
            print "py: call TestPySub2 f"
    
        def g(self):
            print "py: call TestPySub2 g"
    print isinstance(TestPySub2(), TestBase)
    print isinstance(TestPySub2(), TestCppSub)
    TestPySub2().f()
    cpp_call_f(TestPySub2())
    TestPySub2().g()
    cpp_call_g(TestPySub2())
    

    True

    True

    py: call TestPySub2 f

    cpp: call TestBaseWrapper f
    py: call TestPySub2 f

    py: call TestPySub2 g

    cpp: call TestCppSubWrapper g
    py: call TestPySub2 g

    相关文章

      网友评论

          本文标题:基于boostpython,C++父类、子类同时导入Python

          本文链接:https://www.haomeiwen.com/subject/sogvxktx.html