2011-10-11 30 views
1

我在Boost.Python的一個新手,我得到這個錯誤,我希望得到一些幫助。作爲一個更大項目的一部分,我正在爲我有的矢量類寫封裝。正如你將會從代碼中看到的那樣,這個類可以是二維或三維的,但對於目前我遇到的問題並沒有太大的區別。我試圖總結在矢量類我已經定義了一些運營商,並且只要能正常工作的功能(或重載運算符)不返回類型爲向量的「價值」,所以我想這蟒蛇不知道是什麼與我按價值返回的對象做關係。這是代碼:(boost.python)公開重載運算符+()的錯誤。 「類型錯誤:沒有to_python(按值)轉換器找到了」

struct D2 
{ 
    //... 
    typedef Eigen::Matrix< long double, 2, 1 > Vector; 
    //... 
}; 
struct D3 
{ 
    //... 
    typedef Eigen::Matrix< long double, 3, 1 > Vector; 
    //... 
}; 

現在下面的宏定義爲2種可能的尺寸

BOOST_PYTHON_MODULE(types) 
{ 
using namespace boost::python; 

#define GPS_PY_EXPOSE_VECTOR(DIM, NAME)             \ 
     class_<DIM::Vector>(NAME)              \ 
       .def(init<DIM::Vector>())            \ 
       .def("norm", &DIM::Vector::norm)          \ 
       .def("__setitem__", &PyVectorHelper<DIM>::setVectorElem)    \ 
       .def("__getitem__", &PyVectorHelper<DIM>::getVectorElem)    \ 
       .def(self += self)              \ 
       .def(self -= self)              \ 
       .def(self + self) /*Not working!!!*/         \ 
       .def(self - self) /*Not working!!!*/         \ 
       .def("toStr", &PyVectorHelper<DIM>::toPyString)       \ 
       .def("__str__", &PyVectorHelper<DIM>::toStdString)      \ 
     ; 

GPS_PY_EXPOSE_VECTOR(D2, "Vector2D") 
GPS_PY_EXPOSE_VECTOR(D3, "Vector3D") 
} 

上面的代碼工作的權利,做同樣的工作,除了當我嘗試使用「+ 「或 」 - 「 運算符在Python如下:

>>>import types 
>>>v1 = types.Vector2D() 
>>>v2 = types.Vector2D() 
>>>v3 = v1 + v2    //ERROR!!! 

誤差如下:

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: No to_python (by-value) converter found for C++ type: Eigen::CwiseBinaryOp<Eigen::internal::scalar_sum_op<long double>, Eigen::Matrix<long double, 2, 1, 0, 2, 1> const, Eigen::Matrix<long double, 2, 1, 0, 2, 1> const> 

我跟着教程here,我沒有發現任何與互聯網上的錯誤信息有關。

任何幫助是非常歡迎! 在此先感謝。呂克·丹東的回答

呂克丹東後

編輯:謝謝您的回答,我想你說的是什麼,但它不工作。這是我得到的錯誤:

error: no matching function for call to ‘boost::python::class_<Eigen::Matrix<long double, 2, 1, 0, 2, 1>, boost::python::detail::not_specified, boost::python::detail::not_specified, boost::python::detail::not_specified>::def(boost::python::detail::operator_<(boost::python::detail::operator_id)0u, boost::python::self_ns::self_t, boost::python::self_ns::self_t>, boost::python::return_value_policy<boost::python::to_python_value<Eigen::Matrix<long double, 2, 1, 0, 2, 1> >, boost::python::default_call_policies>)’ 

然而,由於你的評論,我有這樣的想法:編寫執行另外一個輔助功能和轉換徵「表達的對象」(這是代表私營類型運營商)。這就是:

template <typename TDim> 
struct PyVectorHelper 
{ 
    //... 
    static typename TDim::Vector sum(typename TDim::Vector const &v1, typename TDim::Vector const &v2) 
    { 
     return v1 + v2; 
    } 
    //... 
}; 

然後

.def("__add__", &PyVectorHelper<DIM>::sum) 

這工作得很好,並不會因爲我想要的,因爲PyVectorHelper<DIM>::sum返回DIM::Vector。問題是幾乎每個由Eigen重載的運算符都會返回一個表達式對象,這意味着我將不得不爲幾乎所有的實現類似的函數!這不會很好也不實際:P。

也許仍然可以使用return_value_policyto_python_value,這樣我可以避免這種繁瑣的操作符重寫?

回答

3

看來基質/載體文庫使用表達模板。在這種情況下,正如你所說的,operator+不是返回一個向量,而是一個表示操作的私有類型。返回的值留在事物的C++端,因爲私有類型沒有註冊,所以無法傳遞給Python。

現在我不是太熟悉Boost.Python的,但我認爲你可以用return value policy解決您的問題。作爲政策傳遞return_value_policy<to_python_value<DIM::Vector> >將強制將返回的類型轉換爲您註冊的DIM::Vector。這看起來像:

.def(self + self, return_value_policy<to_python_value<DIM::Vector> >()) 
+0

請檢查編輯我已經發布到您的答案後,該字符的限制不允許我在這裏做出這樣的評論。 – sinad

+0

@sinad不幸的是,進一步查看文檔,'def'接受運算符表達式的結果(這裏是'self + self')和一個策略,似乎沒有重載,因此您的結果經歷。你的方法是IMO非常有效,我會毫不猶豫地使用預處理器爲我做一些重複性的工作。 –