2013-09-25 117 views
1

我試圖找出如何支持const wchar_t *作爲boost python中公開的函數的返回類型。我的升級版本是1.52,如果這有什麼區別,我正在使用python 2.7。將const const wchar_t *轉換爲python字符串在boost python

不知何故,我不能接受我的轉換功能。我已經在互聯網上看到了這個問題的解決方案的碎片,但沒有任何實際工作或說明如何正確執行。

這是我瑣碎的非工作例如:

#include <string> 
#include <boost/python.hpp> 
using namespace boost::python; 


struct wchar_t_to_python_str 
{ 
    static PyObject* convert(const wchar_t*) 
    { 
     std::string s = "I'm more interested in the function signature than how to do wide char to non-wide char conversion"; 
     return boost::python::incref(boost::python::object(s).ptr()); 
    } 
}; 


void init_module() 
{ 
    to_python_converter<const wchar_t*, wchar_t_to_python_str>(); 
} 

const wchar_t* testWchar() { 
    return L"Hello World"; 
} 
const char* testChar() { 
    return "Hello World"; 
} 

BOOST_PYTHON_MODULE(test) 
{ 
    // This works nicely, const char* is supported 
    def("testChar", testChar); 

    // This doesn't work, fails with this error 
    // 'awBoost::python::detail::specify_a_return_value_policy_to_wrap_functions_returning<T>' 
    // def("testWchar", testWchar); 

    // Throwing in a return value policy fires a compile time assert make_instance_impl 
    // BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >)); 
    // It seems like it gets confused by wchar_t not being a class, but it's hard to know 
    def("testWchar", testWchar, return_value_policy<reference_existing_object>()); 
} 

回答

2

有幾個因素對這個問題:有to_python_converter啓用

  • 轉換功能運行時轉換。
  • Boost.Python不提供builtin conversion支持wchar*。它可能已被忽略,因爲當更新Boost.Python以支持Python 3時,已添加支持std::wstring。缺少內置轉換支持會導致內部類在編譯期間需要合適的CallPolicy。提供的ResultConverterGenerator模型都不適用於此轉換,因爲它們主要影響對象所有權/生命週期而不是類型轉換。

有這些限制範圍內的工作,兩種方法:

下面是一個完整的例子證明這兩種方法:

#include <string> 
#include <boost/function_types/parameter_types.hpp> 
#include <boost/python.hpp> 

/// @brief ResultConverterGenerator used to transform wchar_t to PyObject. 
struct wchar_result_converter 
{ 
    template <class T> struct apply 
    { 
    struct type 
    { 
     /// @brief Convert wchar_t to PyObject. 
     PyObject* operator()(const wchar_t* str) const 
     { 
     // Using the Python/C API may be slighly cleaner. 
     return PyUnicode_FromWideChar(str, wcslen(str)); 

     // Alternatively, Boost.Python's object type can be used. While 
     // Boost.Python does not know how to convert wchar_t to an object, 
     // it does know how to convert std::wstring, so construct 
     // a temporary to help in the conversion. 
     // return boost::python::incref(
     //  boost::python::object(std::wstring(str)).ptr()); 
     } 

     /// @brief Used for documentation. 
     const PyTypeObject* get_pytype() const { return 0; } 
    }; // struct type 
    }; // struct apply 
}; 

/// @brief Modify the return type of a function using supplied CallPolicies. 
template <typename ReturnType, typename Fn, typename Policy> 
boost::python::object return_as(Fn fn, const Policy& policy) 
{ 
    // Build MPL type representing signature of function, injecting the 
    // explicitly provided return type. 
    typedef typename boost::mpl::push_front< 
    typename boost::function_types::parameter_types<Fn>::type, 
    ReturnType 
    >::type signature_type; 

    return boost::python::make_function(fn, policy, signature_type()); 
} 

/// @brief Modify the return type of a function using default_call_policies. 
template <typename ReturnType, typename Fn> 
boost::python::object return_as(Fn fn) 
{ 
    return return_as<ReturnType>(fn, boost::python::default_call_policies()); 
} 

// Test functions. 
const char* testChar() { return "Hello World"; } 
const wchar_t* testWchar() { return L"Hello World"; } 

BOOST_PYTHON_MODULE(example) 
{ 
    namespace python = boost::python; 

    // Expose non-wide test char support. 
    python::def("testChar", testChar); 

    // Expose wide char support by: 
    // - providing a policy to convert the return value. 
    // - manipulating the return type. 
    python::def("testWchar1", &testWchar, 
       python::return_value_policy<wchar_result_converter>()); 
    python::def("testWchar2", return_as<std::wstring>(&testWchar)); 
} 

及其用法:

>>> import example 
>>> a = example.testChar() 
>>> print a 
Hello World 
>>> print type(a) 
<type 'str'> 
>>> b = example.testWchar1() 
>>> print b 
Hello World 
>>> print type(b) 
<type 'unicode'> 
>>> c = example.testWchar2() 
>>> print c 
Hello World 
>>> print type(c) 
<type 'unicode'> 
+0

感謝。我設法得到第一個版本的工作(與return_value_policy),這本質上是我需要繼續前進。在Visual Studio 2012中,我沒有設法解析第二種方法,但我得到了一個令人討厭的boost編譯錯誤。 – Laserallan

+0

如果任何人擅長boost :: mpl調試,則出錯:錯誤C3083:'function_types':'::'左側的符號必須是該行的類型typedef typename boost :: mpl :: push_front < typename boost :: function_types :: parameter_types :: type, ReturnType > :: type signature_type – Laserallan

相關問題