How would I go about creating a custom converter for a C++ type to use in PyROOT?
I have a set of classes that use the nlohmann::json class for passing around configuration information. Now, obviously when I try and use methods on these classes that interact with nlohmann::json PyROOT isn’t particularly happy because it doesn’t know about the class and spits out a warning+error combo
__main__:1: RuntimeWarning: creating converter for unknown type "const nlohmann::basic_json<map,vector,string,bool,long,unsigned long,double,allocator,adl_serializer>&"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: void RDFPlotting::TConfigurable::configure(const nlohmann::basic_json<map,vector,string,bool,long,unsigned long,double,allocator,adl_serializer>& configuration) =>
could not convert argument 1
Would it be possible for me to write a converter (or whatever would be needed) to convert between a python dict and a C++ nlohmann::json object? Ideally this would work two ways - when a C++ method returns nlohmann::json this would become a dict in PyROOT and when one receives a nlohmann::json it would be provided as a dict in PyROOT.
Cheers,
Jon
ROOT Version: 6.14/04 Platform: Not Provided Compiler: gcc 5.4.0
Instead of writing a converter, what you can do is pythonize your cpp type and make it act as a dictionary in python. This basically means injecting to your ROOT.nlohmann.json class, from Python, some behaviour:
The downside of this is that it only works one way: you can operate with your nlohmann.json as dictionaries from Python, but you can’t pass dictionaries to C++ functions that expect a nlohmann.json object.
On the other hand, adding custom converters to PyROOT is not something that is exposed as a public API. In order to add them, you would need to modify Converters.cxx to add your new converter. If you want to go that way, I can point you to an example:
Starting from that line, a conversion between a Python tuple type and a C++ type is added. Thanks to that code, one can pass Python tuples as C++ initializer lists and the tuple elements will be decomposed to feed the constructor of the target C++ class.
OK, I kind of anticipated that this might be tricky .
Needing to modify something inside ROOT itself doesn’t feel particularly portable so I’ll avoid that (this isn’t a showstopper for my code, there are plenty of workarounds).
For pythonizing the code - is there a way to get these functions to be loaded automatically into a pyroot session?
For your pythonizations to be effective, you will need to call a function of yours that does the injections on the nlohmann.json class at the beginning of your script.
We are working on a new version of PyROOT that will allow you to do the same in an easier way. The basic idea will be to define your “pythonizor functions” like this: