Quite similar to this question I want to wrap a function with SWIG which takes a map
of string
s to string
s:
void foo(std::map<std::string, std::string> const& args);
For Python it's enough to create an alias for the map:
namespace std {
%template(map_string_string) map<string, string>;
}
The code generator will create a wrapper function map_string_string
and even automatically use it.
my_module.foo({'a': 'b', 'c', 'd'})
Will correctly be called and values which don't fit the signature will just be left out.
How do I do this for JavaScript?
I tried the same (of course) and the wrapper get's generated but when I try to call foo
like this:
my_module.foo({'a':'b', 'c':'d'});
I get
/path/to/example.js:3
my_module.foo({'a':'b', 'c':'d'});
^
Error: in method 'foo', argument 1 of type 'std::map< std::string,std::string > const &'
at Object.<anonymous> (/path/to/example.js:8:7)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
at Function.Module.runMain (module.js:694:10)
at startup (bootstrap_node.js:204:16)
at bootstrap_node.js:625:3
Even when I try to call the wrapper function map_string_string
I get this error..
Is there another way to write "string maps" in JavaScript? Or is there an easy receipt to wrap an associative array in Swig?
Edit: for completeness I've added the source files I've used:
api.h
#pragma once
#include <string>
#include <map>
#include <iostream>
static void foo(std::string const& value) noexcept {
std::cout << value << std::endl;
}
static void bar(std::map<std::string, std::string> const& args) noexcept {
for (auto && e : args) {
std::cout << e.first << ": " << e.second << std::endl;
}
}
api.i
%module api
%include "std_string.i"
%include "std_map.i"
namespace std {
%template(map_string_string) map<string, string>;
}
%{
#include <api.h>
%}
%include "api.h"
This is the way I build the Python and JavaScript modules:
swig -c++ -python -o api_wrap_python.cxx api.i
g++ -c api_wrap_python.cxx \
-I/usr/include/python3.6m -I . \
-fPIC -std=gnu++11
g++ -shared api_wrap_python.o -o _api.so
swig -c++ -javascript -node -o api_wrap_js.cxx api.i
g++ -c api_wrap_js.cxx \
-I /usr/include/node -I . \
-std=gnu++11 -fPIC -DBUILDING_NODE_EXTENSION
g++ -shared api_wrap_js.o -o api.node
and finally this is how I test them:
node -e "api = require('api.node'); api.foo('some string'); api.bar({'a':'b'});"
python3 -c "import api; api.foo('hello'); api.bar({'a':'b','c':'d'})"
In both cases - Python and JavaScript - api.foo()
is beeing exectued as expected. api.bar()
can be executed on Python but in JavaScript the error I've posted gets thrown.
I looks like the current version of swig
(3.0.12) does not have built-in support for mapping a JavaScript object or primitive to a map
. I think you will have to write your own transformer that takes a JavaScript object and converts it to a C++ map
. See this article for a little help on that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With