【问题标题】:Boost::Python, static factories, and inheritanceBoost::Python、静态工厂和继承
【发布时间】:2010-01-27 16:59:48
【问题描述】:

所以我在这里可能有一个相当独特的用例,但我认为它应该可以工作 - 但它不能正常工作。

基本上,我有一个使用静态工厂方法 ( create ) 的类,该方法将 shared_ptr 返回给新创建的 类的实例。这个类还有一个虚函数,我想从 python 重写并从 C++ 调用。

也许我的代码比我的话能更清楚地表达思想:

#include <string>
#include <iostream>
#include <boost/python.hpp>
#include <boost/enable_shared_from_this.hpp>

using namespace boost::python;
using namespace boost;

//~ Base Class ClassA
class ClassA
    : public enable_shared_from_this<ClassA>
{
protected:
    ClassA(){}
public:

    static shared_ptr<ClassA> create(){ return shared_ptr<ClassA>( new ClassA() ); }

    virtual void quack(){ std::cout<<"quacks like a ClassA Base"<<std::endl; }
};

//~ Wrapper for ClassA
struct WrapClassA : public ClassA, wrapper<WrapClassA>
{

    static shared_ptr<WrapClassA> create(){ return shared_ptr<WrapClassA>( new WrapClassA() ); }

    void quack()
    {
        std::cout<<"quacking like a Wrapper..."<<std::endl;
        if (override f = this->get_override("quack"))
        {
            std::cout<<"... override found!"<<std::endl;
            f();
        }
        else
        {
            std::cout<<"... no override found!"<<std::endl;
            ClassA::quack();
        }
    }

    void default_quack(){ this->ClassA::quack(); }
};

//~ C++ Call Test
void quack( shared_ptr<ClassA> ptr )
{
    ptr->quack();
}

//~ Exposing
BOOST_PYTHON_MODULE(TestCase)
{
    def( "quack", &quack );

    class_<ClassA, shared_ptr<WrapClassA>, noncopyable>( "ClassA", no_init )
        .def( "__init__", make_constructor(&WrapClassA::create) )
        .def( "quack", &ClassA::quack, &WrapClassA::default_quack )
    ;
}

//~ Main
int main()
{

    PyImport_AppendInittab( "TestCase", &initTestCase );
 Py_Initialize();

    boost::python::object main_module((boost::python::handle<>(boost::python::borrowed(PyImport_AddModule("__main__")))));
    boost::python::object main_namespace = main_module.attr("__dict__");

    boost::python::object testcase_module( (boost::python::handle<>(PyImport_ImportModule("TestCase"))) );
    main_namespace["TestCase"] = testcase_module;

    FILE* test_file = fopen("test.py", "r");
    PyRun_SimpleFile(test_file, "test.py");
    fclose( test_file );


    std::cin.get();

 return 0;
}

这是 test.py 的内容:

print "Testing.."

class Derived( TestCase.ClassA ):
    def __init__( self ):
 TestCase.ClassA.__init__( self )
    def quack( self ):
 print( "Quacks like a derived class!" )


Ainst = TestCase.ClassA()
TestCase.quack( Ainst ) #Should print 'Quacks like ClassA Base'

Dinst = Derived()
TestCase.quack( Dinst ) #Should print 'Quacks like a derived class!', but doesn't!

还有输出:

测试中...像 Wrapper 一样嘎嘎作响... ...没有找到覆盖!嘎嘎声 ClassA Base 像 Wrapper 一样嘎嘎作响…… ...没有找到覆盖!嘎嘎声 A类基地

因此,python 中的基类和派生类的行为相同。看起来由于某种原因它没有找到覆盖。我不确定,但这可能与 create() 函数有关。任何想法将不胜感激!

编辑:

在 py 脚本中添加了 pythonquack - 这可以按预期工作:

def pythonquack( Inst ):
    print Inst
    Inst.quack()

如我所料,为 Ainst 和 Dinst 调用它会说“Quacks like a Base”和“Quacks like a Derived”。所以由于某种原因,覆盖没有被传递回 C++。

【问题讨论】:

  • 你好,你会在qauck函数中提供小字语句来打印self的类型和对象吗?这可能会有所帮助。
  • 当然,添加 std::cout
  • 此外,检查 C++ 中所持有的 Python 对象的类型表明“派生”正在作为“A 类”(基础)进入 C++。

标签: c++ python boost


【解决方案1】:

我最终使用 intrusive_ptrs 重新考虑了我的设计。与使用 shared_ptr 相比,使用包装器需要做更多的工作,但效果相当好。感谢大家的宝贵时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2019-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多