2010-01-27 96 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相比,使用包裝的工作還有一些工作要做,但工作得很好。感謝大家的時間。