Search code examples
pythonc++pybind11

Access pybind11 kwargs in C++


I have the following kwargs in python:

interface_dict = {'type':['linear'], 'scope':['ascendant'], height:[-0.4272,0.4272], length:[27.19], 'flag':[True]}
interface.py_interface(**interface_dict)

I'm using pybind11 in C++ to access these python values. I'm trying to store these values in a variant multimap like this:

void py_interface(py::kwargs kwarg){
    std::multimap<std::string, std::variant<float, bool, int, std::string>> kwargs = {
        {"type", (*(kwarg["type"]).begin()).cast<std::string>()}, 
        {"scope", (*(kwarg["scope"]).begin()).cast<std::string>()}, 
        {"height", (*(kwarg["height"]).begin()).cast<float>()}, 
        {"length", (*(kwarg["length"]).begin()).cast<float>()}, 
        {"flag", (*(kwarg["flag"]).begin()).cast<bool>()} 
    }; 
    kwargs.insert(std::pair<std::string, std::variant<float, bool, int, std::string>>("height", /* question how do I access the second value of height to store it here */)); 

My question is how do I access the second value of height (0.4272). I tried using .end() but I get an error:

kwargs.insert(std::pair<std::string, std::variant<float, bool, int, std::string>>("height",(*(kwarg["height"]).end()).cast<float>())); //error unable to cast Python instance to C++ type

Can someone help me?


Solution

  • You can use py::sequence to access items by indices. Just be sure element exist under the given index:

        std::multimap<std::string, std::variant<float, bool, int, std::string>> kwargs = {
            {"type", (*(kwarg["type"]).begin()).cast<std::string>()},
            {"scope", (*(kwarg["scope"]).begin()).cast<std::string>()},
            {"height", py::sequence(kwarg["height"])[1].cast<float>()},
            {"length", (*(kwarg["length"]).begin()).cast<float>()},
            {"flag", (*(kwarg["flag"]).begin()).cast<bool>()}
        };
    

    Another option would be to increment the iterator you create through begin() call:

        std::multimap<std::string, std::variant<float, bool, int, std::string>> kwargs = {
            {"type", (*(kwarg["type"]).begin()).cast<std::string>()},
            {"scope", (*(kwarg["scope"]).begin()).cast<std::string>()},
            {"height", (*(kwarg["height"].begin()++)).cast<float>()},
            {"length", (*(kwarg["length"]).begin()).cast<float>()},
            {"flag", (*(kwarg["flag"]).begin()).cast<bool>()}
        };