2013-09-25 115 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

相关问题