Glib.ustring と Python 3 str の変換
Glib.ustring を使う場合、変換器を書かなきゃならんと思っていてぜんぜんやってなかった。
Boost.Python で既存の C++ 型を使おうとすると、変換器が必要になる。特に別々の世界にある関数を呼び出すときに、引数と戻り値を適当に変換する必要がある(いろんな人が記事を書いてそうなんで細かい説明は省略)。何回書いても即効忘れるのでメモ。といっても組み込みの変換器のコードをほぼコピペしただけだが:
#include <boost/python.hpp> #include <glibmm/ustring.h> namespace me { // Glib.ustring から str への変換 struct ustring_to_python { static PyObject* convert(const Glib::ustring& cc) { return ::PyUnicode_FromStringAndSize(cc.data(), boost::implicit_cast<boost::python::ssize_t>(cc.length())); } static const PyTypeObject* get_pytype() { return &PyUnicode_Type; } }; // str から Glib.ustring への変換 struct ustring_from_python { ustring_from_python() { boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<Glib::ustring>(), &ustring_to_python::get_pytype); } private: static void* convertible(PyObject* p) { if(PyUnicode_Check(p)) return &::PyUnicode_AsUTF8String; if(PyBytes_Check(p)) return &identity; return nullptr; } static void construct(PyObject* p, boost::python::converter::rvalue_from_python_stage1_data* data) { typedef PyObject* (*convertible_function)(PyObject*); convertible_function creator = *static_cast<convertible_function>(data->convertible); boost::python::handle<> intermediate(creator(p)); void* const storage = reinterpret_cast<boost::python::converter::rvalue_from_python_storage<Glib::ustring>*>(data)->storage.bytes; new(storage) Glib::ustring(::PyBytes_AsString(intermediate.get()), ::PyBytes_Size(intermediate.get())); data->convertible = storage; } static PyObject* identity(PyObject* p) { boost::python::incref(p); return p; } }; }
こんな感じで変換器を書いておいて、使う前に登録する。
int main(int argc, char*[]) { ::Py_Initialize(); boost::python::to_python_converter<Glib::ustring, me::ustring_to_python, true>(); me::ustring_from_python(); // なんたら }
これで Glib.ustring と Python の str 型が自動的に相互変換されるようになる。
つまらんな。
で、今回一番気になったのは str だな。Python 2.x → 3.x で大きく変わったにもかかわらず、Boost.Python のドキュメントにはほとんど何も書いてないしな。これも気が向いたらまとめてみよう。













