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).
source to share
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 isT
eitherT 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
source to share