Using Unicode in Boost Python with a C ++ function that accepts std :: wstring

I am using the Boost Python library to port the C ++ class I have so that I can call its methods from Python. My C ++ class Clazz

has public methods:

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

      

I have created BOOST_PYTHON_MODULE

which points to these two methods. The first one that uses std::string

, I can name the fine. However, when I try to call the second one using a Python Unicode string:

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

      

I am getting the error:

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

I was hoping it unicode

would automatically interoperate with std::wstring

, as normal Python string type did with std::string

. However, this does not seem to be the case.

On another thread, someone suggested doing the conversion first:

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

      

However, I am dealing with very large strings and this is ruining the performance of my code as it is O (n) in number of characters x

.

I have the ability to modify the C ++ library I am trying to interact with. Is there a way to pass in Python unicode

types to my C ++ library so that I can use them? I searched the internet all over the world and found links to converters and other things, but their implementation did not fix the above error message (maybe I am not using them correctly).

+3


source to share


1 answer


In short, type conversions usually result in rvalues, and therefore parameters must either be taken by value or by const reference. Hence, change:

void doSomethingWide(std::wstring&);

      

for any of the following:

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

      


Boost.Python added std::wstring

conversions
in 11-SEP-2003. Typically, when type conversions occur in Boost.Python, the resulting object is treated as an rvalue. This behavior is implicitly noted in boost::python::extract

the observer specification:

Converts the stored pointer to result_type

one that is T

either T const&

.



If lvalue conversions were supported, this can lead to awkward semantics for some types. For example, Python immutable strings can be modified using C ++ functions.


Here's 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 use:

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

      

+2


source







All Articles