Typemaps jsoncpp => Python: recursive typemap(outargs)?
Julien Marrec <[email protected]> Wed, 3 Mar 2021 16:01:28 +0100
| Newsgroups | gmane.comp.programming.swig |
|---|---|
| Message-ID | <CAEqKKtxmTDRDN7g-aTs2_ancc8gXpW8XPwfMpYHkxOUozsy-Qw@mail.gmail.com> |
Hello,
First, has anyone wrapped jsoncpp
<https://github.com/open-source-parsers/jsoncpp> in Swig? If I can avoid
reinventing the wheel...
Otherwise, I basically have a Json::Value toJSON() method in C++.
I'd like to return a python dict instead (and a Hash in ruby...). So far,
I've done a workaround by creating a std::string toJSONString() { return
toJSON().toStyledString(); }, and using %pythoncode (and %init with
rb_eval_string in ruby). It works (see at end of email if you're curious),
but I'd like to try a typemap(argout) instead. All my attempts so far have
miserably failed, probably because:
1. This is pretty much the first time I tried to do a typemap, and,
2. I have no clue how to do a recursive call to the typemap(argout)
itself.
Here is one of my attempts (I tried with Json::Value instead of Json::Value
* too)
#if defined SWIGPYTHON
%typemap(argout) Json::Value * {
if ($1->isIntegral()) {
$result = PyLong_FromLongLong($1->asInt64());
} else if ($1->isNumeric()) {
$result = PyFloat_FromDouble($1->asDouble());
} else if ($1->isString()) {
$result = PyUnicode_FromString($->.asString());
} else if ($1->isArray()) {
$result = PyList_New();
for( const auto& n : *$1) {
// TODO: this should do a recursive call to convert n (which
is Json::Value) to a python type...
PyList_Append(n);
}
} else if ($1->isObject()) {
$result = PyDict_New();
for( const auto& id : $1->getMemberNames()) {
// TODO: this should do a recursive call to convert *$1[id]
(which is a Json::Value) to a python type...
PyDict_SetItemString($result, id.c_str(), *$1[id]);
}
}
}
#endif
The documentation for Json::Value is at
https://open-source-parsers.github.io/jsoncpp-docs/doxygen/class_json_1_1_value.html
*If someone could nudge me in the right direction, that'd be much
appreciated.*
Thank you,
Julien
------------------------------
For reference my current workaround: in epJSON.i:
#if defined SWIGRUBY
// This isn't super clean and there might be a better way with
typemaps in SWIG rather than using a String in between,
// but still helpful I think: we redefine toJSON that will return a
native ruby hash. 'json' is part of ruby stdlib since at least ruby
2.5.5
%init %{
rb_eval_string("OpenStudio::EPJSON.module_eval {
define_method(:toJSON) { |arg| json_str = self.toJSONString(arg);
require 'json'; JSON.load(json_str); }; module_function(:toJSON) }");
%}
#endif
#if defined SWIGPYTHON
// Let's use monkey-patching via unbound functions
// Edit: not even needed here
%pythoncode %{
# Manually added: Lazy-load the json module (python std lib) and
return a dict via toJSONString
def toJSON(*args) -> dict:
import json
return json.loads(toJSONString(*args))
%}
#endif
--
Julien Marrec, EBCP, BPI MFBA
Owner at EffiBEM <http://www.effibem.com>
T: +33 6 95 14 42 13
LinkedIn (en <https://www.linkedin.com/in/julienmarrec>) *| *(fr
<https://fr.linkedin.com/in/julienmarrec/fr>) :
<http://www.linkedin.com/in/julienmarrec>
_______________________________________________
Swig-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/swig-user