2010-01-27 88 views
4

所以我可能在这里有一个相当独特的用例,但我认为它应该工作 - 但它不能正常工作。Boost :: Python,静态工厂和继承

基本上,我有一个类,它使用静态工厂方法(创建),返回一个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! 

和输出:

测试...像包装一样嘎嘎... ...没有发现重写!庸医像 ClassA基地像一个包装嘎嘎... ...没有重写发现! quacks like ClassA Base

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

编辑:

新增pythonquack到PY脚本 - 这个工作过程预计:

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

调用它Ainst和Dinst说:“叫声也像基”,“像一个派生江湖医生” ,如我所料。所以出于某种原因,覆盖不会传回C++。

+0

嗨,你会在qauck函数中提供小型打印语句来打印自己的类型和对象吗?这可能有帮助。 – Anycorn 2010-01-27 18:22:05

+0

当然,添加 std :: cout << typeid(* this).name()<< std :: endl; 给嘎嘎函数返回“struct WrapClassA”,并加入 std :: cout << typeid(* ptr).name()<< std :: endl; 返回“struct WrapClassA”。 我很抱歉,如果你的意思是python对象而不是C++对象。 – 2010-01-27 20:46:08

+0

此外,在C++中检查持有的Python对象的类型表明“派生”正在以C类为'ClassA'(Base)。 – 2010-01-27 21:06:35

回答

1

我最终使用intrusive_ptrs重新考虑了我的设计。与使用shared_ptr相比,使用包装的工作还有一些工作要做,但工作得很好。感谢大家的时间。