2016-09-12 71 views
0

在約升壓許多例子蟒蛇:: Python中,你會看到類似:如何公開一個模板類作爲一個類的boost ::蟒蛇

using namespace boost::python; 
typedef class_<std::vector<float>> VectorFloat; 

然後,當然,如果你需要你double矢量將有第二類叫DoubleVector左右。 在我看來,這不是很「pythonic」。如果C++中的一個(模板化)類實際上是Python中的一個類,它會採用像, ..., type='float', ... ,這樣的參數,那會更直觀(我認爲)。通過這種方式,該課程在pydoc中也只出現一次,並且只能添加一次到boost::python module

所以我們可以說,我們有一個簡單的模板類爲我們的C++代碼:

template <typename T> 
MyClass 
{ 
    T val; 

public: 
    MyClass(const T& tVal) : val(tVal) {} 

    T getVal()    { return val; } 
    void setVal(const T& tVal) { val = tVal; } 
}; 

現在我們要編寫Python的一個接口。到目前爲止,我的想法:

使用boost ::變種

typedef boost::variant<MyClass<float>, MyClass<double>> VariantClass;  

class MyPythonClass 
{ 
    VariantClass vClass; 

public: 
    MyPythonClass(
     const PyObject& tVal, 
     const boost::python::str& type) 
    { 
     using namespace boost::python; 
     std::string type_string = extract<std::string>(type); 

     if(type_string == "float") 
     { 
      float f = extract<float>(tVal); 
      vClass = MyClass(f); 
     } 
     else if(type_string == "double") 
     { 
      double d = extract<double>(tVal); 
      vClass = MyClass(d); 
     } 
    } 

    boost::python::PyObject* getVal() 
    { 
     // What to put here? 
    } 

    void setVal(const boost::python::PyObject& tVal) 
    { 
     //What to put here? 
    } 
}; 

BOOST_PYTHON_MODULE(my_module) 
{ 
    class_<MyPythonClass>("MyClass", init<boost::python::PyObject, int, boost::python::str>).def("getVal", &MyClass::getVal()); 
} 

這種解決方案的一個明顯缺點是我猜的boost ::變體可以與有很大的不同wheras我的課幾乎工種身份,除了他們存儲的數據的類型。所以可能有更多的信息被抽象出來而不是必要的。

所以我想這個問題歸結爲例子中的兩個空函數。然而,更清潔,更短或更少的「如果」鏈式答案當然也會被接受。正如標題所說,它是關於模板化類和boost :: python,而不是關於boost :: variant。

+0

要將boost :: variant轉換爲python對象,請使用static_visitor。要轉換另一種方式,您需要在運行時詢問python對象的類型。 –

回答

1

這裏有一些混亂的來源。首先,在Python中,object已經基本上是一個變體 - 一切都是object。而在C++中,類模板不是類型 - 它是創建類型的一個配方。所以,如果你想從C++到Python暴露MyClass<T>,你應該揭露所有的MyClass<T>s

我會寫一個函數模板,做綁定:

template <class T> 
void bind_MyClass(const char* name) { 
    class_<MyClass<T>>(name, init<T const&>()) 
     .add_property("val", &MyClass<T>::getVal, &MyClass<T>::setVal); 
     ; 
} 

然後叫它:

bind_MyClass<float>("MyClassFloat"); 
bind_MyClass<double>("MyClassDouble");