我正在尝试公开一个c ++函数,将const wchar_t *作为python中的参数。在我看来,const wchar_t *不是一个支持的输入类型,它自动作为python字符串公开,然后像普通的const char *一样自动转换。
是否可以添加某种自动获得此功能的输入类型转换器?我知道我可以添加trampoline函数并自己进行unicode转换,但让它自动运行会更方便。
我的提升版本是1.52,我在64位窗口上使用python 2.7。
以下是显示问题的简单c ++序列的示例代码:
#include <boost/python.hpp>
#include <iostream>
using namespace boost::python;
void testWcharParam(const wchar_t* str) {
std::wcout << str << std::endl;
}
void testCharParam(const char* str) {
std::wcout << str << std::endl;
}
BOOST_PYTHON_MODULE(test)
{
def("testWcharParam", testWcharParam);
def("testCharParam", testCharParam);
}
在python中导入并运行它时,我得到以下结果:
>>> import test
>>> test.testCharParam('test')
test
>>> test.testWcharParam('test')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
test.testWcharParam(str)
did not match C++ signature:
testWcharParam(wchar_t const * __ptr64)
>>>
出于某种原因,此处http://www.boost.org/doc/libs/1_52_0/libs/python/doc/v2/faq.html#custom_string的字符串方法对原始wchar_t *不起作用。
编辑:添加了缺失的包含和平台信息。
编辑:在增强文档中添加了有关示例的说明
答案 0 :(得分:3)
据我所知,无法从Python窄字符串(str
)到const wchar_t*
进行自动转换。
当Boost.Python尝试从Python对象转换时,它会在堆栈上分配内存以保存目标类型,然后尝试查找为目标类型注册的转换器。在这种情况下,目标类型将是const wchar_t*
。一旦转换器指示PyObject
是转换的有效候选者,转换将发生,初始化堆栈分配的内存中的目标类型。由于Python / C API仅支持在编码时创建新的PyObject
,因此内存管理成为一个问题,因为Boost.Python仅为wchar_t*
分配了内存。
由于Boost.Python不提供在使用转换后的值后调用的后挂钩,因此一个简单的折衷方案可能是将const wchar_t*
的参数类型更改为std::wstring
。当std::wstring
管理自己的内存时,Boost.Python可以将PyObject
宽字符串复制到其中。此外,必要时,Boost.Python会在转换为std::wstring
期间将窄字符串编码为宽字符串。
示例代码:
#include <iostream>
#include <boost/python.hpp>
void testWcharParam(std::wstring str) { std::wcout << str << std::endl; }
void testCharParam(const char* str) { std::wcout << str << std::endl; }
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::def("testWcharParam", testWcharParam);
python::def("testCharParam", testCharParam);
}
用法:
>>> import example
>>> example.testCharParam('test 1')
test 1
>>> example.testWcharParam(u'test 2')
test 2
>>> example.testWcharParam('test 3')
test 3
答案 1 :(得分:1)
我没有使用过Boost Python,但Python 2中的wchar_t是一个Unicode字符串,所以请尝试:
>>> test.testWcharParam(u'test')
答案 2 :(得分:1)
这是我最终使用的:
void* convert_to_wcstring(PyObject* obj)
{
if(PyString_Check(obj)) {
throw_error_already_set();
} else if(PyUnicode_Check(obj)) {
return PyUnicode_AsUnicode(obj);
}
throw_error_already_set();
return 0;
}
然后将其作为转换器添加到:
BOOST_PYTHON_MODULE(test)
{
converter::registry::insert(convert_to_wcstring, type_id<wchar_t>(),&converter::wrap_pytype<&PyString_Type>::get_pytype);
...
}
只要输入参数是unicode类型而不是普通的字符串类型,这就可以工作。对于我的初始示例,它将给出以下结果:
# Works
test.testWcharParam(u'test')
# Doesn't work
test.testWcharParam('test')
在我的例子中,C ++ API比python更严格,这意味着我在那里比在C ++端更好地清理输入字符串。
感谢所有的答案,你引导我朝着正确的方向前进,但我不得不调整一些事情,以便找到解决我确切用例的方法。