using nlohmann::json with cppyy?

Question:

Is it possible to pass a python dict into a function expecting a nlohmann::json (nlohmann/json) object via cppyy? This question has to have come up by now, but I wasn’t able to find anything on it.

Minimal example to reproduce (without regard to performance/safety, pls forgive):

test-json.h

#include <iostream>
#include <nlohmann/json.hpp>

using nlohmann::json;

void print_name_and_age(json j) {
    std::cout << j["name"] << "n"
              << j["age"] << "n";
} 

test-cppyy.py

import cppyy
cppyy.include('test-json.h')

from cppyy.gbl import print_name_and_age

some_dict = {
    "name": "alfred",
    "age": 25
}

print_name_and_age(some_dict)

runs into

    print_name_and_age(some_dict)
NotImplementedError: void ::print_name_and_age(nlohmann::json j) =>
    NotImplementedError: could not convert argument 1 (this method cannot (yet) be called)

I would like to be able to pass a python dict into the C++ function, and receive it as a nlohmann::json object. I presume I would need to write some custom converter for this?

Design requirement/background (optional)

I have a reinforcement learning environment class (written in C++) that needs to accept some configuration to initialize it (in its constructor). Everything’s all fine passing a nlohmann::json object into the constructor while in the C++ domain, but I have a Python wrapper around the class too, written with cppyy that provides similar functionality to the C++ interface.
Uptill now, because of the aforementioned issue, I’ve been forced to receive a const std::map<std::string, float>& in the constructor instead of a nlohmann::json, which is what a python dict containing only str -> float mappings easily gets converted to by cppyy. But this obviously limits my input json files to only contain floats as values (my usecase requires having strings as keys but strings, ints, floats and bools as values in the JSON file). I can ofcourse write some pre-processing code to encode my heterogenous python dict into a homogenous str->float mapping on the python front (and do the same for C++) but I’d like a cleaner solution, if possible.

Could anyone please help me achieve passing a python dict into the cppyy-imported C++ function and have it converted into a nlohmann::json object in the C++ function? If this requires forking cppyy to add extra converter code/too much trouble I presume I would need to use a std::map<std::string, std::any / variant> alternative? I haven’t worked alot with std::any/variant, would like to ask if this would even be possible – python dict to map<string, any> – if this is the best alternative to a custom converter – in terms of performance / clean elegant code.

Environment:

Python 3.9.13

C++17 ( I believe cppyy-2.4.0 doesn’t support C++20 yet, I don’t have any constraint on the C++ standard)

cppyy==2.3.1
cppyy-backend==1.14.8
cppyy-cling==6.25.3
cppyythonizations==1.2.1

MacOS Monterey, Apple M1

Asked By: Siraj Qazi

||

Answers: