繁体   English   中英

使用Boost Python导出const wchar_t * c ++函数

[英]Exporting const wchar_t* c++ function with Boost Python

我正在尝试公开一个将const wchar_t *作为python参数的c ++函数。 在我看来,const wchar_t *不是受支持的输入类型,它会自动显示为python字符串,然后像普通的const char *一样自动转换。

是否可以添加某种输入类型转换器来自动解决此问题? 我知道我可以添加蹦床功能并自己进行unicode转换,但是使它自动正确运行会更加方便。

我的增强版是1.52,我正在64位Windows上使用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 *不起作用。

编辑:添加了缺少的包含和平台信息。

编辑:在boost文档中的示例上添加了注释

据我所知,没有办法将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

我没有使用Boost Python,但是Python 2中的wchar_t是Unicode字符串,因此请尝试:

>>> test.testWcharParam(u'test')

我最终使用的是:

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 ++相比,我在这里清理输入字符串的位置要好得多。

感谢您提供的所有答案,您使我朝着正确的方向发展,但是我不得不稍作调整,以便获得一些解决我的确切用例的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM