Возвращение std :: unordered_map ключ как pybind11 :: bytes - PullRequest
1 голос
/ 06 августа 2020

Рассмотрим следующий код Pybind11:

#include <string>
#include <unordered_map>

#include <pybind11/stl.h>
#include <pybind11/pybind11.h>

struct foo {
    foo() {
        data.emplace("\xde\xad\xbe\xaf", 1);
    }
    std::unordered_map<std::string, int> data;
};

PYBIND11_MODULE(example, m) {
    pybind11::class_<foo>(m, "foo")
    .def(pybind11::init())
    .def_readonly("data", &foo::data);
}

При вызове python2 example.foo().data он выдает UnicodeDecodeError - потому что ключи data не содержат допустимого UTF. Глядя на pybind11 / cast.h, мы видим, что string_caster::cast() всегда пытается выполнить decode_utfN(), и это вызывает вышеуказанное исключение.

Как убедить Pybind11 обрабатывать ключи как bytes?

1 Ответ

1 голос
/ 06 августа 2020

Как насчет копирования значений в dict с bytes в качестве ключей? Это сработает?

struct foo {
    foo() {
        data.emplace("\xde\xad\xbe\xaf", 1);
    }
    std::unordered_map<std::string, int> data;
};

PYBIND11_MODULE(example, m) {
    pybind11::class_<foo>(m, "foo")
            .def(pybind11::init())
            .def_property_readonly("data", [](const foo& f)
                                   {
                                       pybind11::dict d;
                                       for(const auto& v : f.data )
                                       {
                                           d[pybind11::bytes(v.first)] = v.second;
                                       }
                                       return d;
                                   });
}
>>> import example
>>> example.foo().data
{b'\xde\xad\xbe\xaf': 1}
>>> 
...