简体   繁体   English

在Boost Python中使用Unicode,使用带有std :: wstring的C ++函数

[英]Using Unicode in Boost Python with a C++ function that takes std::wstring

I am using the Boost Python library to wrap a C++ class I have so that I can call its methods from Python. 我正在使用Boost Python库来包装我拥有的C ++类,以便我可以从Python调用它的方法。 My C++ class Clazz has public methods: 我的C ++类Clazz有公共方法:

void doSomething(std::string& s) { ... }
void doSomethingWide(std::wstring& ws) { ... }

I've created a BOOST_PYTHON_MODULE which points to these two methods. 我创建了一个指向这两种方法的BOOST_PYTHON_MODULE The first one which uses std::string I'm able to call fine. 第一个使用std::string我可以调用。 However, when I try to call the second one with a Python Unicode string: 但是,当我尝试使用Python Unicode字符串调用第二个时:

x = u'hello'
Clazz.doSomethingWide(x)

I get the error: 我收到错误:

ArgumentError: Python argument types in Clazz.doSomethingWide(Clazz, unicode) did not match C++ signature: doSomething(Clazz, std::wstring)

I had hoped that unicode would automatically interface with std::wstring as the regular Python string type did with std::string . 我曾希望unicode会自动与std::wstring接口,因为常规的Python字符串类型与std::string However, this appears to not be the case. 但是,情况似乎并非如此。

In another thread, someone suggested first doing the conversion: 在另一个帖子中,有人建议先进行转换:

x = str(x.encode('utf-8'))

However, I am dealing with very large strings and this destroys the performance of my code since it is O(n) in the number of characters of x . 但是,我正在处理非常大的字符串,这会破坏我的代码的性能,因为它是x的字符数O(n)

I do have the ability to modify the C++ library that I'm trying to interface with. 有修改,我试图与接口的C ++库的能力。 Is there a way to pass in Python unicode types into my C++ library in a way that I can use them? 有没有办法以我可以使用它的方式将Python unicode类型传递到我的C ++库中? I've searched the Internet far and wide and found some references to converters and other things, but implementing them did not fix the above error message (very possibly I'm not using them correctly). 我已经远程搜索了互联网,并发现了一些转换器和其他东西的引用,但实现它们并没有修复上面的错误信息(很可能我没有正确使用它们)。

In short, type conversions generally result in rvalue objects, and thus the parameters must either accept by value or by const reference. 简而言之,类型转换通常会产生rvalue对象,因此参数必须通过值或const引用接受。 Hence, change: 因此,改变:

void doSomethingWide(std::wstring&);

to either of the following: 以下任一项:

void doSomethingWide(std::wstring);
void doSomethingWide(const std::wstring&);

Boost.Python added std::wstring conversions on 11-SEP-2003. Boost.Python在11-SEP-2003上添加了std::wstring转换 As a general rule, when type conversions occur in Boost.Python, the resulting object is treated as an rvalue. 作为一般规则,当在Boost.Python中发生类型转换时,结果对象将被视为右值。 This behavior is indirectly noted in the boost::python::extract observer specification: boost::python::extract观察者规范中间接注意到此行为:

Converts the stored pointer to result_type , which is either T or T const& . 将存储的指针转换为result_type ,它是TT const&

If lvalue conversions were supported, it could introduce awkward semantics for some types. 如果支持左值转换,则可能会为某些类型引入笨拙的语义。 For example, immutable Python strings could be modified by C++ functions. 例如,C ++函数可以修改不可变的Python字符串。


Here is a complete minimal example: 这是一个完整的最小例子:

#include <iostream>
#include <string>
#include <boost/python.hpp>

class spam
{
public:
  void doSomething(const std::string& str)
  {
    std::cout << "spam::doSomething(): " << str << std::endl;
  }

  void doSomethingWide(const std::wstring& str)
  {
    std::wcout << "spam::doSomethingWide(): " << str << std::endl;
  }
};

BOOST_PYTHON_MODULE(example)
{
  namespace python = boost::python;
  python::class_<spam>("Spam")
    .def("doSomething", &spam::doSomething)
    .def("doSomethingWide", &spam::doSomethingWide)
    ;
}

Interactive usage: 互动用法:

>>> import example
>>> spam = example.Spam()
>>> spam.doSomething("test")
spam::doSomething(): test
>>> spam.doSomethingWide(u"test")
spam::doSomethingWide(): test

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

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