diff options
Diffstat (limited to 'Lib/javascript/napi')
32 files changed, 2863 insertions, 0 deletions
diff --git a/Lib/javascript/napi/argcargv.i b/Lib/javascript/napi/argcargv.i new file mode 100644 index 000000000..4a146047e --- /dev/null +++ b/Lib/javascript/napi/argcargv.i @@ -0,0 +1,66 @@ +/* ------------------------------------------------------------ + * SWIG library containing argc and argv multi-argument typemaps + * ------------------------------------------------------------ */ + +%{ +SWIGINTERN int SWIG_AsVal_string (Napi::Value valRef, Napi::String *str) +{ + if (!valRef.IsString()) { + return SWIG_TypeError; + } + if(str != SWIG_NULLPTR) { + *str = valRef.ToString(); + } + return SWIG_OK; +} +%} + +%typemap(in) (int ARGC, char **ARGV) { + $1_ltype i, len; + size_t arraysize; + Napi::Array array; + if (!$input.IsArray()) { + SWIG_exception_fail(SWIG_ERROR, "not array"); + } + array = $input.As<Napi::Array>(); + len = array.Length(); + arraysize = (len+1)*sizeof($*2_ltype); + $1 = len; + $2 = ($2_ltype) malloc(arraysize); + if ($2 == SWIG_NULLPTR) { + SWIG_exception_fail(SWIG_ERROR, "memory allocation of array failed"); + } + memset($2, 0, arraysize); + for (i = 0; i < len; i++) { + int res, slen; + $*2_ltype pstr; + Napi::String napi_str; + Napi::Value jsvalue = array.Get(i); + res = SWIG_AsVal_string(jsvalue, &napi_str); + if (!SWIG_IsOK(res)) { + SWIG_exception_fail(SWIG_ERROR, "failed to convert to string"); + } + std::string str = napi_str.Utf8Value(); + slen = str.size(); + pstr = ($*2_ltype) malloc(slen + 1); + if (pstr == SWIG_NULLPTR) { + SWIG_exception_fail(SWIG_ERROR, "memory allocation of a string failed"); + } + if (slen) { + memcpy(pstr, str.c_str(), slen); + } + pstr[slen] = 0; + $2[i] = pstr; + } + $2[i] = SWIG_NULLPTR; +} + +%typemap(freearg) (int ARGC, char **ARGV) { + if ($2 != SWIG_NULLPTR) { + $1_ltype i; + for (i = 0; i < $1; i++) { + free((void *)$2[i]); + } + free((void *)$2); + } +} diff --git a/Lib/javascript/napi/arrays_javascript.i b/Lib/javascript/napi/arrays_javascript.i new file mode 100644 index 000000000..c02097818 --- /dev/null +++ b/Lib/javascript/napi/arrays_javascript.i @@ -0,0 +1,88 @@ +/* ----------------------------------------------------------------------------- + * arrays_javascript.i + * + * These typemaps give more natural support for arrays. The typemaps are not efficient + * as there is a lot of copying of the array values whenever the array is passed to C/C++ + * from JavaScript and vice versa. The JavaScript array is expected to be the same size as the C array. + * An exception is thrown if they are not. + * + * Example usage: + * Wrapping: + * + * %include <arrays_javascript.i> + * %inline %{ + * extern int FiddleSticks[3]; + * %} + * + * Use from JavaScript like this: + * + * var fs = [10, 11, 12]; + * example.FiddleSticks = fs; + * fs = example.FiddleSticks; + * ----------------------------------------------------------------------------- */ + + +%fragment("SWIG_NAPI_GetIntProperty", "header", fragment=SWIG_AsVal_frag(int)) {} +%fragment("SWIG_NAPI_GetNumberProperty", "header", fragment=SWIG_AsVal_frag(double)) {} +%fragment("SWIG_NAPI_OutInt", "header", fragment=SWIG_From_frag(int)) {} +%fragment("SWIG_NAPI_OutNumber", "header", fragment=SWIG_From_frag(double)) {} + +%define JAVASCRIPT_ARRAYS_IN_DECL(NAME, CTYPE, ANY, ANYLENGTH) + +%typemap(in, fragment=NAME) CTYPE[ANY] { + if ($input.IsArray()) { + Napi::Env env = $input.Env(); + // Convert into Array + Napi::Array array = $input.As<Napi::Array>(); + + int length = ANYLENGTH; + + $1 = ($*1_ltype *)malloc(sizeof($*1_ltype) * length); + + // Get each element from array + for (int i = 0; i < length; i++) { + Napi::Value jsvalue = array.Get(i); + $*1_ltype temp; + + // Get primitive value from JSObject + int res = SWIG_AsVal(CTYPE)(jsvalue, &temp); + if (!SWIG_IsOK(res)) { + SWIG_Error(SWIG_ERROR, "Failed to convert $input to double"); + } + arg$argnum[i] = temp; + } + } else { + Napi::Env env = $input.Env(); + SWIG_Error(SWIG_ERROR, "$input is not an array"); + } +} + +%typemap(freearg) CTYPE[ANY] { + free($1); +} + +%enddef + +%define JAVASCRIPT_ARRAYS_OUT_DECL(NAME, CTYPE) + +%typemap(out, fragment=NAME) CTYPE[ANY] { + int length = $1_dim0; + Napi::Array array = Napi::Array::New(env, length); + + for (int i = 0; i < length; i++) { + array.Set(i, SWIG_From(CTYPE)($1[i])); + } + + $result = array; +} + +%enddef + +JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetIntProperty", int, , array.Length()) +JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetIntProperty", int, ANY, $1_dim0) +JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetNumberProperty", double, , array.Length()) +JAVASCRIPT_ARRAYS_IN_DECL("SWIG_NAPI_GetNumberProperty", double, ANY, $1_dim0) + +JAVASCRIPT_ARRAYS_OUT_DECL("SWIG_NAPI_OutInt", int) +JAVASCRIPT_ARRAYS_OUT_DECL("SWIG_NAPI_OutNumber", double) + diff --git a/Lib/javascript/napi/ccomplex.i b/Lib/javascript/napi/ccomplex.i new file mode 100644 index 000000000..e58dbf719 --- /dev/null +++ b/Lib/javascript/napi/ccomplex.i @@ -0,0 +1,27 @@ +/* ----------------------------------------------------------------------------- + * ccomplex.i + * + * C complex typemaps + * ISO C99: 7.3 Complex arithmetic <complex.h> + * ----------------------------------------------------------------------------- */ + + +%include <javascriptcomplex.swg> + +%{ +#include <complex.h> +%} + +#define complex _Complex + +/* C complex constructor */ +#define CCplxConst(r, i) ((r) + I*(i)) + +%swig_cplxflt_convn(float _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(double _Complex, CCplxConst, creal, cimag); +%swig_cplxdbl_convn(_Complex, CCplxConst, creal, cimag); + +/* declaring the typemaps */ +%typemaps_primitive(SWIG_TYPECHECK_CPLXFLT, float _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, double _Complex); +%typemaps_primitive(SWIG_TYPECHECK_CPLXDBL, _Complex); diff --git a/Lib/javascript/napi/cdata.i b/Lib/javascript/napi/cdata.i new file mode 100644 index 000000000..367965990 --- /dev/null +++ b/Lib/javascript/napi/cdata.i @@ -0,0 +1 @@ +%include <typemaps/cdata.swg> diff --git a/Lib/javascript/napi/cmalloc.i b/Lib/javascript/napi/cmalloc.i new file mode 100644 index 000000000..248f06b96 --- /dev/null +++ b/Lib/javascript/napi/cmalloc.i @@ -0,0 +1 @@ +%include <typemaps/cmalloc.swg> diff --git a/Lib/javascript/napi/complex.i b/Lib/javascript/napi/complex.i new file mode 100644 index 000000000..4c3b3c5e2 --- /dev/null +++ b/Lib/javascript/napi/complex.i @@ -0,0 +1,6 @@ +#ifdef __cplusplus +%include <std_complex.i> +#else +%include <ccomplex.i> +#endif + diff --git a/Lib/javascript/napi/exception.i b/Lib/javascript/napi/exception.i new file mode 100644 index 000000000..0246cfde8 --- /dev/null +++ b/Lib/javascript/napi/exception.i @@ -0,0 +1 @@ +%include <typemaps/exception.swg> diff --git a/Lib/javascript/napi/factory.i b/Lib/javascript/napi/factory.i new file mode 100644 index 000000000..46a0a8733 --- /dev/null +++ b/Lib/javascript/napi/factory.i @@ -0,0 +1 @@ +%include <typemaps/factory.swg> diff --git a/Lib/javascript/napi/javascript.swg b/Lib/javascript/napi/javascript.swg new file mode 100644 index 000000000..c37a3848c --- /dev/null +++ b/Lib/javascript/napi/javascript.swg @@ -0,0 +1,17 @@ +/* ----------------------------------------------------------------------------- + * javascript.swg + * + * Javascript typemaps + * ----------------------------------------------------------------------------- */ + +%include <typemaps/swigmacros.swg> + +%include <javascripttypemaps.swg> + +%include <javascriptruntime.swg> + +%include <javascriptkw.swg> + +%include <javascriptcode.swg> + +%include <javascriptinit.swg> diff --git a/Lib/javascript/napi/javascriptcode.swg b/Lib/javascript/napi/javascriptcode.swg new file mode 100644 index 000000000..26e8aded5 --- /dev/null +++ b/Lib/javascript/napi/javascriptcode.swg @@ -0,0 +1,880 @@ +/* ----------------------------------------------------------------------------- + * js_ctor: template for wrapping a ctor. + * - $jswrapper: wrapper of called ctor + * - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none) + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * - $jsargcount: number of arguments + * - $jsargrequired: minimum number of arguments + * - $jsmangledname: mangled name of class + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ + +%fragment("js_ctor", "templates") %{ +template <typename SWIG_OBJ_WRAP> +// js_ctor +// This is the main constructor +$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(const Napi::CallbackInfo &info) + : $jsparent_templ<SWIG_OBJ_WRAP>(true, info) { + Napi::Env env = info.Env(); + + this->info = SWIGTYPE_$jsmangledtype; + if (info.Length() == 1 && info[0].IsExternal()) { + // This constructor has been called internally from C++/SWIG + // to wrap an already existing C++ object in JS + this->self = info[0].As<Napi::External<void>>().Data(); + this->owned = false; + return; + } + this->owned = true; + + $jslocals + if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) { + SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + } + $jscode + this->self = result; + return; + goto fail; +fail: + return; +} + +// This is the bypass constructor to be used from child classes +template <typename SWIG_OBJ_WRAP> +$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(bool, const Napi::CallbackInfo &info) + : $jsparent_templ<SWIG_OBJ_WRAP>(true, info) {} +%} + + +/* ----------------------------------------------------------------------------- + * js_veto_ctor: a vetoing ctor for abstract classes + * - $jsmangledname: mangled name of class + * - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none) + * ----------------------------------------------------------------------------- */ +%fragment ("js_veto_ctor", "templates") +%{ +// js_veto_ctor +template <typename SWIG_OBJ_WRAP> +$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(const Napi::CallbackInfo &info) + : $jsparent_templ<SWIG_OBJ_WRAP>(true, info) { + Napi::Env env = info.Env(); + if (info.Length() == 1 && info[0].IsExternal()) { + // This constructor has been called internally from C++/SWIG + // to wrap an already existing C++ object in JS as its + // base abstract class + this->self = info[0].As<Napi::External<void>>().Data(); + this->owned = false; + return; + } + SWIG_Error(SWIG_ERROR, "Class $jsname can not be instantiated"); + return; + goto fail; +fail: + return; +} + +// This is the extendable constructor to be used from child classes +template <typename SWIG_OBJ_WRAP> +$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(bool, const Napi::CallbackInfo &info) + : $jsparent_templ<SWIG_OBJ_WRAP>(true, info) { +} +%} + + +/* ----------------------------------------------------------------------------- + * js_ctor_dispatcher: dispatcher for overloaded constructors + * - $jsmangledname: mangled name of class + * - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none) + * - $jsdispatchcases: part containing code for dispatching + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor_dispatcher", "templates") +%{ +// js_ctor_dispatcher +template <typename SWIG_OBJ_WRAP> +$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(const Napi::CallbackInfo &info) + : $jsparent_templ<SWIG_OBJ_WRAP>(true, info) { + Napi::Env env = info.Env(); + Napi::Object self; + NAPI_CHECK_RESULT(info.This().ToObject(), self); + this->info = SWIGTYPE_$jsmangledtype; + if (info.Length() == 1 && info[0].IsExternal()) { + // This constructor has been called internally from C++/SWIG + // to wrap an already existing C++ object in JS + this->self = info[0].As<Napi::External<void>>().Data(); + this->owned = false; + return; + } + + // switch all cases by means of series of if-returns. + $jsdispatchcases + + // default: + SWIG_Error(SWIG_ERROR, "Illegal arguments for construction of $jsmangledname"); + + goto fail; +fail: + return; +} + +// This is the extendable constructor to be used from child classes +template <typename SWIG_OBJ_WRAP> +$jsmangledname_templ<SWIG_OBJ_WRAP>::$jsmangledname_templ(bool, const Napi::CallbackInfo &info) + : $jsparent_templ<SWIG_OBJ_WRAP>(true, info) { +} +%} + + +/* ----------------------------------------------------------------------------- + * js_overloaded_ctor: template for wrapping a ctor. + * - $jswrapper: wrapper of called ctor + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * - $jsargcount: number of arguments + * - $jsargrequired: minimum number of arguments + * - $jsmangledtype: mangled type of class + * ----------------------------------------------------------------------------- */ +%fragment("js_overloaded_ctor", "templates") %{ +// js_overloaded_ctor +template <typename SWIG_OBJ_WRAP> +Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Object self; + $jslocals + NAPI_CHECK_RESULT(info.This().ToObject(), self); + this->owned = true; + if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) { + SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + } + $jscode + this->self = result; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_ctor_dispatch_case: template for a dispatch case for calling an overloaded ctor. + * - $jsargcount: number of arguments of called ctor + * - $jsargrequired: minimum number of arguments + * - $jswrapper: wrapper of called ctor + * + * Note: a try-catch-like mechanism is used to switch cases + * ----------------------------------------------------------------------------- */ +%fragment ("js_ctor_dispatch_case", "templates") +%{ + // js_ctor_dispatch_case + if(static_cast<int>(info.Length()) >= $jsargrequired && static_cast<int>(info.Length()) <= $jsargcount) { +#ifdef NAPI_CPP_EXCEPTIONS + bool tryNext = false; + try { + $jswrapper(info); + } catch (const Napi::TypeError &) { + tryNext = true; + } catch (const Napi::Error &e) { + throw e; + } + if (!tryNext) + return; +#else + $jswrapper(info); + if (env.IsExceptionPending()) { + Napi::Error e = env.GetAndClearPendingException(); + Napi::Value typeErrorValue; + bool isTypeError; + Napi::Function typeErrorCons; + // Yes, this is ugly + // TODO: Fix this in Node.js when the core team grows up + NAPI_CHECK_RESULT(env.Global().Get("TypeError"), typeErrorValue); + typeErrorCons = typeErrorValue.As<Napi::Function>(); + NAPI_CHECK_RESULT(e.Value().InstanceOf(typeErrorCons), isTypeError); + if (!isTypeError) { + // This is not the error you are looking for + e.ThrowAsJavaScriptException(); + SWIG_fail; + } + } else { + return; + } +#endif + } +%} + + +/* ----------------------------------------------------------------------------- + * js_check_arg: template for checking if an argument exists + * - $jsarg: number of argument + * ----------------------------------------------------------------------------- */ +%fragment ("js_check_arg", "templates") +%{if(info.Length() > $jsarg)%} + + +/* ----------------------------------------------------------------------------- + * js_dtor: template for a destructor wrapper + * - $jsmangledname: mangled class name + * - $jstype: class type + * ----------------------------------------------------------------------------- */ +%fragment ("js_dtor", "templates") +%{ +// js_dtor +template <typename SWIG_OBJ_WRAP> +$jsmangledname_templ<SWIG_OBJ_WRAP>::~$jsmangledname_templ() { +} +%} + + +/* ----------------------------------------------------------------------------- + * js_dtoroverride: template for a destructor wrapper + * - ${classname_mangled}: mangled class name + * - $jstype: class type + * - ${destructor_action}: The custom destructor action to invoke. + * ----------------------------------------------------------------------------- */ +%fragment ("js_dtoroverride", "templates") +%{ +// js_dtoroverride +template <typename SWIG_OBJ_WRAP> +${classname_mangled}_templ<SWIG_OBJ_WRAP>::~${classname_mangled}_templ() { + auto arg1 = reinterpret_cast<$jstype>(this->self); + if (this->owned && arg1) { + ${destructor_action} + this->self = nullptr; + } +} +%} + +/* ----------------------------------------------------------------------------- + * js_global_getter: template for global getter function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_global_getter", "templates") +%{ +// js_global_getter +Napi::Value $jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + $jscode + return jsresult; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_global_setter: template for global setter function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_global_setter", "templates") +%{ +// js_global_setter +void $jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value value = info.Length() > 0 ? info[0] : Napi::Value(); + Napi::Value jsresult; + $jslocals + $jscode + return; + + goto fail; +fail: + return; +} +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_register_global_variable: template for a statement that registers a global variable + * - $jsname: variable name + * - $jsparent: parent namespace + * - $jsgetter: wrapper of the getter function + * - $jssetter: wrapper of the setter function + * + * Note: this template is also used for global variables. + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_global_variable", "templates") +%{ + // jsnapi_register_global_variable + do { + Napi::PropertyDescriptor pd = Napi::PropertyDescriptor::Accessor<$jsgetter, $jssetter>("$jsname"); + NAPI_CHECK_MAYBE($jsparent.DefineProperties({pd})); + } while (0); +%} + + +/* ----------------------------------------------------------------------------- + * js_global_function: template for function wrappers + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jsargcount: number of arguments + * - $jsargrequired: minimum number of arguments + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_global_function", "templates") +%{ +// js_global_function +Napi::Value $jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) { + SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + } + + $jscode + return jsresult; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_global_function_dispatcher: template for a global function dispatcher for + * global overloaded functions + * - $jswrapper: wrapper function name + * - $jsname: name of the wrapped function + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_global_function_dispatcher", "templates") +%{ +// js_global_function_dispatcher +Napi::Value $jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jscode + + SWIG_Error(SWIG_ERROR, "Illegal arguments for function $jsname."); + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_register_global_function: template for a statement that registers a global function + * - $jsname: function name + * - $jsparent: parent namespace + * - $jswrapper: name of the JS wrapper + * + * Note: this template is also used for global variables. + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_global_function", "templates") +%{ + // jsnapi_register_global_function + do { + Napi::PropertyDescriptor pd = Napi::PropertyDescriptor::Function("$jsname", $jswrapper); + NAPI_CHECK_MAYBE($jsparent.DefineProperties({pd})); + } while (0); +%} + + +/* ----------------------------------------------------------------------------- + * js_getter: template for getter function wrappers + * - $jsmangledname: mangled class name + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_getter", "templates") +%{ +// js_getter +template <typename SWIG_OBJ_WRAP> +Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + $jscode + return jsresult; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_setter: template for setter function wrappers + * - $jsmangledname: mangled class name + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_setter", "templates") +%{ +// js_setter +template <typename SWIG_OBJ_WRAP> +void $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info, const Napi::Value &value) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + $jscode + return; + + goto fail; +fail: + return; +} +%} + + +/* ----------------------------------------------------------------------------- + * js_function: template for function wrappers + * - $jsmangledname: mangled class name + * - $jswrapper: wrapper function name + * - $jsargcount: minimum number of arguments + * - $jsargrequired: minimum number of arguments + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_function", "templates") +%{ +// js_function +template <typename SWIG_OBJ_WRAP> +Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + if(static_cast<int>(info.Length()) < $jsargrequired || static_cast<int>(info.Length()) > $jsargcount) { + SWIG_Error(SWIG_ERROR, "Illegal number of arguments for $jswrapper."); + } + + $jscode + return jsresult; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_function_dispatcher: template for a function dispatcher for overloaded functions + * - $jsmangledname: mangled class name + * - $jswrapper: wrapper function name + * - $jsname: name of the wrapped function + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment("js_function_dispatcher", "templates") +%{ +// js_function_dispatcher +template <typename SWIG_OBJ_WRAP> +Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jscode + + SWIG_Error(SWIG_ERROR, "Illegal arguments for function $jsname."); + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_overloaded_function: template for a overloaded function + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_overloaded_function", "templates") +%{ +// js_overloaded_function +template <typename SWIG_OBJ_WRAP> +Napi::Value $jsmangledname_templ<SWIG_OBJ_WRAP>::$jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + $jscode + return jsresult; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_global_overloaded_function: template for a global overloaded function + * - $jswrapper: wrapper function name + * - $jslocals: locals part of wrapper + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_global_overloaded_function", "templates") +%{ +// js_global_overloaded_function +Napi::Value $jswrapper(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + $jslocals + $jscode + return jsresult; + + goto fail; +fail: + return Napi::Value(); +} +%} + + +/* ----------------------------------------------------------------------------- + * js_function_dispatch_case: template for a case used in the function dispatcher + * - $jswrapper: wrapper function name + * - $jsargcount: number of arguments of overloaded function + * - $jsargrequired: minimum number of arguments + * - $jscode: code part of wrapper + * ----------------------------------------------------------------------------- */ +%fragment ("js_function_dispatch_case", "templates") +%{ + // js_function_dispatch_case + if(static_cast<int>(info.Length()) >= $jsargrequired && static_cast<int>(info.Length()) <= $jsargcount) { +#ifdef NAPI_CPP_EXCEPTIONS + bool tryNext = false; + try { + jsresult = $jswrapper(info); + } catch (const Napi::TypeError &) { + tryNext = true; + } catch (const Napi::Error &e) { + throw e; + } + if (!tryNext) + return jsresult; +#else + $jswrapper(info); + if (env.IsExceptionPending()) { + Napi::Error e = env.GetAndClearPendingException(); + Napi::Value typeErrorValue; + bool isTypeError; + Napi::Function typeErrorCons; + // Yes, this is ugly + // TODO: Fix this in Node.js when the core team grows up + NAPI_CHECK_RESULT(env.Global().Get("TypeError"), typeErrorValue); + typeErrorCons = typeErrorValue.As<Napi::Function>(); + NAPI_CHECK_RESULT(e.Value().InstanceOf(typeErrorCons), isTypeError); + if (!isTypeError) { + // This is not the error you are looking for + e.ThrowAsJavaScriptException(); + SWIG_fail; + } + } else { + return jsresult; + } +#endif + } +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_class_prologue_template: template for a class prologue + * - $jsmangledname: mangled class name + * - $jsparent: mangled name of parent (or SWIG_NAPI_ObjectWrap if none) + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_class_prologue_template", "templates") +%{ + // jsnapi_class_prologue_template + template <typename SWIG_OBJ_WRAP> + class $jsmangledname_templ : public $jsparent_templ<SWIG_OBJ_WRAP> { + public: + $jsmangledname_templ(const Napi::CallbackInfo &); + $jsmangledname_templ(bool, const Napi::CallbackInfo &); +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_class_dtor_declaration: template for a class destructor declaration + * - $jsmangledname: mangled class name + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_class_dtor_declaration", "templates") +%{ + virtual ~$jsmangledname_templ(); +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_class_method_declaration: template for a class method declaration + * - $jsmangledname: mangled class name + * - $jswrapper: method name + * - $jsstatic: static modifier + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_class_method_declaration", "templates") +%{ + // jsnapi_class_method_declaration + $jsstatic Napi::Value $jswrapper(const Napi::CallbackInfo &); +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_class_setter_declaration: template for a class method declaration + * - $jsmangledname: mangled class name + * - $jswrapper: method name + * - $jsstatic: static modifier + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_class_setter_declaration", "templates") +%{ + // jsnapi_class_setter_declaration + $jsstatic void $jswrapper(const Napi::CallbackInfo &, const Napi::Value &); +%} + + + +/* ----------------------------------------------------------------------------- + * jsnapi_class_epilogue_template: template for a class epilogue + * - $jsmangledname: mangled class name + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_class_epilogue_template", "templates") +%{ + // jsnapi_class_epilogue_template + static void JS_veto_set_static_variable(const Napi::CallbackInfo &, const Napi::Value &); + void JS_veto_set_variable(const Napi::CallbackInfo &, const Napi::Value &); +}; + +template <typename SWIG_OBJ_WRAP> +void $jsmangledname_templ<SWIG_OBJ_WRAP>::JS_veto_set_static_variable(const Napi::CallbackInfo &info, const Napi::Value &value) { + SWIG_NAPI_Raise(info.Env(), "Tried to write read-only variable."); +} + +template <typename SWIG_OBJ_WRAP> +void $jsmangledname_templ<SWIG_OBJ_WRAP>::JS_veto_set_variable(const Napi::CallbackInfo &info, const Napi::Value &value) { + SWIG_NAPI_Raise(info.Env(), "Tried to write read-only variable."); +} +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_class_instance: template for a class declaration instance + * - $jsmangledname: mangled class name + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_declare_class_instance", "templates") +%{ + // jsnapi_class_instance + class $jsmangledname_inst : public $jsmangledname_templ<$jsmangledname_inst> { + public: + using $jsmangledname_templ::$jsmangledname_templ; + virtual ~$jsmangledname_inst() {}; + static void GetMembers( + Napi::Env, + std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &, + std::map<std::string, $jsmangledname_templ::PropertyDescriptor> & + ); + static Napi::Function GetClass(Napi::Env); + }; +%} + + +/* + * Inheritance is still not officially supported in NAPI + * Refer to this for my workaround: + * https://mmomtchev.medium.com/c-class-inheritance-with-node-api-and-node-addon-api-c180334d9902 + */ + +/* ----------------------------------------------------------------------------- + * jsnapi_inherited_class_prologue_template: template for a class prologue + * - $jsmangledname: mangled class name + * - $jsparent: mangled name of parent class + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_inherited_class_prologue_template", "templates") +%{ + // jsnapi_inherited_class_prologue_template + SWIG_NAPI_ClientData $jsmangledname_clientData; + template <typename SWIG_OBJ_WRAP> + class $jsmangledname_templ : public $jsparent_templ<SWIG_OBJ_WRAP> { + public: + $jsmangledname_templ(const Napi::CallbackInfo& info); +%} + + +/* ----------------------------------------------------------------------------- + * jsnapi_getclass: template for creating a class object + * - $jsname: class name + * - $jsmangledname: mangled class name + * - $jsfunctions: member functions + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_getclass", "templates") +%{ + /* Class: $jsname ($jsmangledname) */ + // jsnapi_getclass +Napi::Function $jsmangledname_inst::GetClass(Napi::Env env) { + std::map<std::string, $jsmangledname_templ::PropertyDescriptor> members, staticMembers; + GetMembers(env, members, staticMembers); + + std::vector<$jsmangledname_inst::PropertyDescriptor> symbolTable; + for (auto it = members.begin(); it != members.end(); it++) + symbolTable.push_back(it->second); + for (auto it = staticMembers.begin(); it != staticMembers.end(); it++) + symbolTable.push_back(it->second); + + return Napi::ObjectWrap<$jsmangledname_inst>::DefineClass(env, "$jsname", symbolTable); +} + +void $jsmangledname_inst::GetMembers( + Napi::Env env, + std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &members, + std::map<std::string, $jsmangledname_templ::PropertyDescriptor> &staticMembers +) { + std::map<std::string, $jsparent_templ<$jsparent_inst>::PropertyDescriptor> baseMembers, baseStaticMembers; + $jsparent_inst::GetMembers(env, baseMembers, baseStaticMembers); + members.insert(baseMembers.begin(), baseMembers.end()); + staticMembers.insert(staticMembers.begin(), staticMembers.end()); + + /* register wrapper functions */ + $jsnapiwrappers + /* add static class functions and variables */ + $jsnapistaticwrappers +} +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_registerclass: template for regsitering a class object + * - $jsname: class name + * - $jsmangledname: mangled class name + * - $jsparent: parent namespace + * - $jsmangledtype: mangled class type + * - $jsclassidx: class index in the class table + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_registerclass", "templates") +%{ + + /* Class: $jsname ($jsmangledname) */ + // jsnapi_registerclass + Napi::Function $jsmangledname_ctor = $jsmangledname_inst::GetClass(env); + $jsparent.Set("$jsname", $jsmangledname_ctor); + if (SWIGTYPE_$jsmangledtype->clientdata == nullptr) { + SWIGTYPE_$jsmangledtype->clientdata = new size_t($jsclassidx); + } + Napi::FunctionReference *$jsmangledname_ctor_ref = new Napi::FunctionReference(); + *$jsmangledname_ctor_ref = Napi::Persistent($jsmangledname_ctor); + env.GetInstanceData<EnvInstanceData>()->ctor[$jsclassidx] = $jsmangledname_ctor_ref; +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_setup_inheritance: setup inheritance between two classes + * - $jsname: class name + * - $jsmangledname: mangled class name + * - $jsparent: mangled name of parent class + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_setup_inheritance", "templates") +%{ + // Inheritance for $jsmangledname ($jsname) <- $jsparent + // jsnapi_setup_inheritance + do { + Napi::Value protoBase, protoSub; + NAPI_CHECK_RESULT($jsmangledname_ctor.Get("prototype"), protoSub); + NAPI_CHECK_RESULT($jsparent_ctor.Get("prototype"), protoBase); + NAPI_CHECK_MAYBE(setProto.Call({$jsmangledname_ctor, $jsparent_ctor})); + NAPI_CHECK_MAYBE(setProto.Call({protoSub, protoBase})); + } while (0); +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_create_namespace: template for a statement that creates a namespace object. + * - $jsmangledname: mangled namespace name + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_create_namespace", "templates") +%{ + // jsnapi_create_namespace + Napi::Object $jsmangledname = Napi::Object::New(env); +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_register_namespace: template for a statement that registers a namespace in a parent namespace. + * - $jsname: name of namespace + * - $jsmangledname: mangled name of namespace + * - $jsparent: mangled name of parent namespace + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_namespace", "templates") +%{ + // jsnapi_register_namespace + NAPI_CHECK_MAYBE($jsparent.Set("$jsname", $jsmangledname)); +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_member_function_descriptor: template for a statement that registers a member function. + * - $jsmangledname: mangled class name + * - $jsname: name of the function + * - $jswrapper: wrapper of the member function + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_member_function", "templates") +%{ + // jsnapi_member_function_descriptor + members.erase("$jsname"); + members.insert({"$jsname", + $jsmangledname_templ::InstanceMethod("$jsname", + &$jsmangledname_templ::$jswrapper, + static_cast<napi_property_attributes>(napi_writable | napi_configurable)) + }); +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_register_member_variable: template for a statement that registers a member variable. + * - $jsname: name of the function + * - $jsmangledname: mangled class name + * - $jsgetter: wrapper of the getter function + * - $jssetter: wrapper of the setter function + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_member_variable", "templates") +%{ + // jsnapi_register_member_variable + members.erase("$jsname"); + members.insert({"$jsname", + $jsmangledname_templ::InstanceAccessor("$jsname", + &$jsmangledname_templ::$jsgetter, + &$jsmangledname_templ::$jssetter, + static_cast<napi_property_attributes>(napi_writable | napi_enumerable | napi_configurable)) + }); +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_register_static_function: template for a statement that registers a static class function. + * - $jsname: function name + * - $jsmangledname: mangled class name + * - $jswrapper: wrapper of the function + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_static_function", "templates") +%{ + // jsnapi_register_static_function + staticMembers.erase("$jsname"); + staticMembers.insert({"$jsname", + StaticMethod("$jsname", + &$jsmangledname_templ::$jswrapper, + static_cast<napi_property_attributes>(napi_writable | napi_configurable)) + }); +%} + +/* ----------------------------------------------------------------------------- + * jsnapi_register_static_variable: template for a statement that registers a static variable. + * - $jsname: variable name + * - $jsmangledname: mangled class name + * - $jsgetter: wrapper of the getter function + * - $jssetter: wrapper of the setter function + * ----------------------------------------------------------------------------- */ +%fragment("jsnapi_register_static_variable", "templates") +%{ + // jsnapi_register_static_variable + staticMembers.erase("$jsname"); + staticMembers.insert({"$jsname", + StaticAccessor("$jsname", + &$jsmangledname_templ::$jsgetter, + &$jsmangledname_templ::$jssetter, + static_cast<napi_property_attributes>(napi_writable | napi_enumerable | napi_configurable)) + }); +%} diff --git a/Lib/javascript/napi/javascriptcomplex.swg b/Lib/javascript/napi/javascriptcomplex.swg new file mode 100644 index 000000000..3b0864408 --- /dev/null +++ b/Lib/javascript/napi/javascriptcomplex.swg @@ -0,0 +1,116 @@ +/* + Defines the As/From converters for double/float complex, you need to + provide complex Type, the Name you want to use in the converters, + the complex Constructor method, and the Real and Imag complex + accessor methods. + + See the std_complex.i and ccomplex.i for concrete examples. +*/ + +/* the common from converter */ +%define %swig_fromcplx_conv(Type, Real, Imag) +%fragment(SWIG_From_frag(Type),"header", + fragment=SWIG_From_frag(double)) +{ +SWIGINTERNINLINE Napi::Value +SWIG_From_dec(Type)(%ifcplusplus(const Type&, Type) c) +{ + Napi::Array vals = Napi::Array::New(0); + + vals.Set(0, SWIG_From(double)(Real(c))); + vals.Set(1, SWIG_From(double)(Imag(c))); + return vals; +} +} +%enddef + +/* the double case */ +%define %swig_cplxdbl_conv(Type, Constructor, Real, Imag) +%fragment(SWIG_AsVal_frag(Type),"header", + fragment=SWIG_AsVal_frag(double)) +{ +SWIGINTERN int +SWIG_AsVal_dec(Type) (Napi::Value o, Type* val) +{ + if (o.IsArray()) { + Napi::Array array = Napi::Array::Cast(o); + + if (array->Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2]."); + double re, im; + Napi::Value r; + + r = array.Get(0); + if (!r.IsNumber()) { + return SWIG_TypeError; + } + re = r.ToNumber().DoubleValue(); + + r = array.Get(1); + if (!r.IsNumber()) { + return SWIG_TypeError; + } + im = r.ToNumber().DoubleValue(); + + if (val) *val = Constructor(re, im); + return SWIG_OK; + } else if (o.IsNumber()) { + double d = o.ToNumber().DoubleValue(); + if (val) *val = Constructor(d, 0.0); + return SWIG_OK; + } + return SWIG_TypeError; +} +} +%swig_fromcplx_conv(Type, Real, Imag); +%enddef + +/* the float case */ +%define %swig_cplxflt_conv(Type, Constructor, Real, Imag) +%fragment(SWIG_AsVal_frag(Type),"header", + fragment=SWIG_AsVal_frag(float)) { +SWIGINTERN int +SWIG_AsVal_dec(Type) (Napi::Value o, Type* val) +{ + if (o.IsArray()) { + Napi::Array array = o.As<Napi::Array>(); + + if (array.Length() != 2) SWIG_Error(SWIG_TypeError, "Illegal argument for complex: must be array[2]."); + double re, im; + Napi::Value r; + + r = array.Get(0); + if (!r.IsNumber()) { + return SWIG_TypeError; + } + re = r.ToNumber().DoubleValue(); + + r = array.Get(1); + if (!r.IsNumber()) { + return SWIG_TypeError; + } + im = r.ToNumber().DoubleValue(); + + if ((-FLT_MAX <= re && re <= FLT_MAX) && (-FLT_MAX <= im && im <= FLT_MAX)) { + if (val) *val = Constructor(%numeric_cast(re, float), + %numeric_cast(im, float)); + return SWIG_OK; + } else { + return SWIG_OverflowError; + } + } else if (o.IsNumber()) { + float f = static_cast<float>(o.ToNumber().DoubleValue()); + if (val) *val = Constructor(f, 0.0); + return SWIG_OK; + } + return SWIG_TypeError; +} +} +%swig_fromcplx_conv(Type, Real, Imag); +%enddef + +#define %swig_cplxflt_convn(Type, Constructor, Real, Imag) \ +%swig_cplxflt_conv(Type, Constructor, Real, Imag) + + +#define %swig_cplxdbl_convn(Type, Constructor, Real, Imag) \ +%swig_cplxdbl_conv(Type, Constructor, Real, Imag) diff --git a/Lib/javascript/napi/javascriptfragments.swg b/Lib/javascript/napi/javascriptfragments.swg new file mode 100644 index 000000000..4778bf033 --- /dev/null +++ b/Lib/javascript/napi/javascriptfragments.swg @@ -0,0 +1,23 @@ +/* + + Create a file with this name, 'javascriptfragments.swg', in your working + directory and add all the %fragments you want to take precedence + over the default ones defined by swig. + + For example, if you add: + + %fragment(SWIG_AsVal_frag(int),"header") { + SWIGINTERNINLINE int + SWIG_AsVal(int)(PyObject *obj, int *val) + { + <your code here>; + } + } + + this will replace the code used to retrieve an integer value for all + the typemaps that need it, including: + + int, std::vector<int>, std::list<std::pair<int,int> >, etc. + + +*/ diff --git a/Lib/javascript/napi/javascriptinit.swg b/Lib/javascript/napi/javascriptinit.swg new file mode 100644 index 000000000..e8b3d38c7 --- /dev/null +++ b/Lib/javascript/napi/javascriptinit.swg @@ -0,0 +1,111 @@ +%insert(header) %{ +#include <assert.h> +%} + +%insert(init) %{ + +EnvInstanceData::EnvInstanceData(Napi::Env env, swig_module_info *swig_module) : +env(env), SWIG_NAPI_ObjectWrapCtor(nullptr), ctor(nullptr), swig_module(swig_module) { + ctor = new Napi::FunctionReference*[swig_module->size + 1]; + for (size_t i = 0; i <= swig_module->size; i++) { + ctor[i] = nullptr; + } +} + +EnvInstanceData::~EnvInstanceData() { + for (size_t i = 0; i <= swig_module->size; i++) { + if (ctor[i] != nullptr) + delete ctor[i]; + ctor[i] = nullptr; + } + delete [] ctor; + delete SWIG_NAPI_ObjectWrapCtor; +} + +SWIGRUNTIME void +SWIG_NAPI_SetModule(Napi::Env env, swig_module_info *swig_module) { + auto data = new EnvInstanceData(env, swig_module); + env.SetInstanceData(data); +} + +SWIGRUNTIME swig_module_info * +SWIG_NAPI_GetModule(Napi::Env env) { + auto data = env.GetInstanceData<EnvInstanceData>(); + if (data == nullptr) return nullptr; + return data->swig_module; +} + +#define SWIG_GetModule(clientdata) SWIG_NAPI_GetModule(clientdata) +#define SWIG_SetModule(clientdata, pointer) SWIG_NAPI_SetModule(clientdata, pointer) +#define SWIG_INIT_CLIENT_DATA_TYPE Napi::Env + +%} + +%insert(init) "swiginit.swg" + +// Open the initializer function definition here + +%fragment ("js_initializer_define", "templates") %{ +#define SWIG_NAPI_INIT $jsname_initialize +%} + +%insert(init) %{ +Napi::Object Init(Napi::Env env, Napi::Object exports) { + SWIG_InitializeModule(env); +%} + +/* ----------------------------------------------------------------------------- + * js_init_inheritance: template for enabling the inheritance + * ----------------------------------------------------------------------------- */ +%fragment("js_init_inheritance", "templates") +%{ + Napi::Value jsObjectValue, jsSetProtoValue; + Napi::Object jsObject; + Napi::Function setProto; + NAPI_CHECK_RESULT(env.Global().Get("Object"), jsObjectValue); + NAPI_CHECK_RESULT(jsObjectValue.ToObject(), jsObject); + NAPI_CHECK_RESULT(jsObject.Get("setPrototypeOf"), jsSetProtoValue); + setProto = jsSetProtoValue.As<Napi::Function>(); +%} + +/* ----------------------------------------------------------------------------- + * js_initializer: template for the module initializer function + * - $jsname: module name + * - $jsnapipreinheritance: the previous template + * - $jsnapinspaces: part with code creating namespace objects + * - $jsnapiwrappers: part with code that registers wrapper functions + * - $jsnapiinitinheritance: part with inherit statements + * - $jsnapistaticwrappers: part with code adding static functions to class objects + * - $jsnapiregisterclasses: part with code that registers class objects in namespaces + * - $jsnapiregisternspaces: part with code that registers namespaces in parent namespaces + * ----------------------------------------------------------------------------- */ +%fragment("js_initializer", "templates") +%{ + Napi::Function SWIG_NAPI_ObjectWrap_ctor = SWIG_NAPI_ObjectWrap_inst::GetClass(env); + Napi::FunctionReference *SWIG_NAPI_ObjectWrap_ctor_ref = new Napi::FunctionReference(); + *SWIG_NAPI_ObjectWrap_ctor_ref = Napi::Persistent(SWIG_NAPI_ObjectWrap_ctor); + env.GetInstanceData<EnvInstanceData>()->SWIG_NAPI_ObjectWrapCtor = SWIG_NAPI_ObjectWrap_ctor_ref; + + /* create objects for namespaces */ + $jsnapinspaces + + /* register classes */ + $jsnapiregisterclasses + + /* enable inheritance */ + $jsnapipreinheritance + + /* setup inheritances */ + $jsnapiinitinheritance + + /* create and register namespace objects */ + $jsnapiregisternspaces + + return exports; + goto fail; +fail: + return Napi::Object(); +} + +NODE_API_MODULE($jsname, Init) +%} diff --git a/Lib/javascript/napi/javascriptprimtypes.swg b/Lib/javascript/napi/javascriptprimtypes.swg new file mode 100644 index 000000000..e6224f917 --- /dev/null +++ b/Lib/javascript/napi/javascriptprimtypes.swg @@ -0,0 +1,387 @@ +/* ------------------------------------------------------------ + * Primitive Types + * ------------------------------------------------------------ */ + +/* boolean */ + +%fragment(SWIG_From_frag(bool),"header", "header") { +SWIGINTERN +Napi::Value SWIG_From_bool(Napi::Env env, bool val) +{ + return Napi::Boolean::New(env, val); +} +} + + +%fragment(SWIG_AsVal_frag(bool),"header", + fragment=SWIG_AsVal_frag(long)) { +SWIGINTERN +int SWIG_AsVal_dec(bool)(Napi::Value obj, bool *val) +{ + if(!obj.IsBoolean()) { + return SWIG_TypeError; + } + + Napi::Boolean b; + NAPI_CHECK_RESULT(obj.ToBoolean(), b); + if (val) *val = b.Value(); + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + +/* char */ + +%fragment(SWIG_From_frag(unsigned char), "header") { +SWIGINTERNINLINE Napi::Value +SWIG_From_unsigned_SS_char(Napi::Env env, unsigned char c) +{ + return Napi::Number::New(env, static_cast<double>(c)); +} +} + + +%fragment(SWIG_From_frag(signed char), "header") { +SWIGINTERNINLINE Napi::Value +SWIG_From_signed_SS_char(Napi::Env env, signed char c) +{ + return Napi::Number::New(env, static_cast<double>(c)); +} +} + +/* int */ + +%fragment(SWIG_From_frag(int), "header") { +SWIGINTERN +Napi::Value SWIG_From_int(Napi::Env env, int val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(int),"header") { +SWIGINTERN +int SWIG_AsVal_dec(int)(Napi::Value valRef, int* val) +{ + if (!valRef.IsNumber()) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(valRef.ToNumber(), num); + *val = static_cast<int>(num.Int32Value()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + + +/* unsigned int */ + +%fragment(SWIG_From_frag(unsigned int), "header") { +SWIGINTERN +Napi::Value SWIG_From_unsigned_SS_int(Napi::Env env, unsigned int val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(unsigned int),"header") { +SWIGINTERN +int SWIG_AsVal_dec(unsigned int)(Napi::Value valRef, unsigned int* val) +{ + if (!valRef.IsNumber()) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(valRef.ToNumber(), num); + if (num.Int64Value() < 0) { + return SWIG_TypeError; + } + *val = static_cast<unsigned int>(num.Uint32Value()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + + +/* short */ + +%fragment("SWIG_Env_FromShort", "header") { +SWIGINTERN +Napi::Value SWIG_From_short(Napi::Env env, short val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(short),"header") { +SWIGINTERN +int SWIG_AsVal_dec(short)(Napi::Value valRef, short* val) +{ + if (!valRef.IsNumber()) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(valRef.ToNumber(), num); + *val = static_cast<short>(num.Int32Value()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + + +/* unsigned short */ + +%fragment(SWIG_From_frag(unsigned short), "header") { +SWIGINTERN +Napi::Value SWIG_From_unsigned_SS_short(Napi::Env env, unsigned short val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(unsigned short),"header") { +SWIGINTERN +int SWIG_AsVal_dec(unsigned short)(Napi::Value valRef, unsigned short* val) +{ + if (!valRef.IsNumber()) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(valRef.ToNumber(), num); + if (num.Int64Value() < 0) { + return SWIG_TypeError; + } + *val = static_cast<unsigned short>(num.Uint32Value()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + + +/* long */ + +%fragment(SWIG_From_frag(long), "header") { +SWIGINTERN +Napi::Value SWIG_From_long(Napi::Env env, long val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(long),"header", + fragment="SWIG_CanCastAsInteger") { +SWIGINTERN +int SWIG_AsVal_dec(long)(Napi::Value obj, long* val) +{ + if (!obj.IsNumber()) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(obj.ToNumber(), num); + *val = static_cast<long>(num.Int64Value()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + +/* unsigned long */ + +%fragment(SWIG_From_frag(unsigned long), "header") { +SWIGINTERN +Napi::Value SWIG_From_unsigned_SS_long(Napi::Env env, unsigned long val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(unsigned long),"header", + fragment="SWIG_CanCastAsInteger") { +SWIGINTERN +int SWIG_AsVal_dec(unsigned long)(Napi::Value obj, unsigned long *val) +{ + if(!obj.IsNumber()) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(obj.ToNumber(), num); + if (num.Int64Value() < 0) { + return SWIG_TypeError; + } + *val = static_cast<unsigned long>(num.Int64Value()); + } + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + +/* long long */ + +%fragment(SWIG_From_frag(long long), "header", fragment="SWIG_LongLongAvailable") { +%#ifdef SWIG_LONG_LONG_AVAILABLE +SWIGINTERN +Napi::Value SWIG_From_long_SS_long(Napi::Env env, long long val) +{ + return Napi::Number::New(env, val); +} +%#endif +} + +%fragment(SWIG_AsVal_frag(long long),"header", + fragment=SWIG_AsVal_frag(long), + fragment="SWIG_CanCastAsInteger", + fragment="SWIG_LongLongAvailable") { +%#ifdef SWIG_LONG_LONG_AVAILABLE +SWIGINTERN +int SWIG_AsVal_dec(long long)(Napi::Value obj, long long* val) +{ + if(!obj.IsNumber()) { + return SWIG_TypeError; + } + + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(obj.ToNumber(), num); + *val = static_cast<long long>(num.Int64Value()); + } + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +%#endif +} + +/* unsigned long long */ + +%fragment(SWIG_From_frag(unsigned long long), "header", fragment="SWIG_LongLongAvailable") { +%#ifdef SWIG_LONG_LONG_AVAILABLE +SWIGINTERN +Napi::Value SWIG_From_unsigned_SS_long_SS_long(Napi::Env env, unsigned long long val) +{ + return Napi::Number::New(env, val); +} +%#endif +} + + +%fragment(SWIG_AsVal_frag(unsigned long long),"header", + fragment=SWIG_AsVal_frag(unsigned long), + fragment="SWIG_CanCastAsInteger", + fragment="SWIG_LongLongAvailable") { +%#ifdef SWIG_LONG_LONG_AVAILABLE +SWIGINTERN +int SWIG_AsVal_dec(unsigned long long)(Napi::Value obj, unsigned long long *val) +{ + if(!obj.IsNumber()) { + return SWIG_TypeError; + } + if (obj.ToNumber().Int64Value() < 0) { + return SWIG_TypeError; + } + if (val) { + Napi::Number num; + NAPI_CHECK_RESULT(obj.ToNumber(), num); + *val = static_cast<unsigned long long>(num.Int64Value()); + } + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +%#endif +} + + +/* float */ + +%fragment(SWIG_From_frag(float), "header") { +SWIGINTERN +Napi::Value SWIG_From_float(Napi::Env env, float val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(float),"header") { +SWIGINTERN +int SWIG_AsVal_dec(float)(Napi::Value obj, float *val) +{ + if(!obj.IsNumber()) { + return SWIG_TypeError; + } + + if(val) { + Napi::Number num; + NAPI_CHECK_RESULT(obj.ToNumber(), num); + *val = static_cast<float>(num.DoubleValue()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} + + +/* double */ + +%fragment(SWIG_From_frag(double), "header") { +SWIGINTERN +Napi::Value SWIG_From_double(Napi::Env env, double val) +{ + return Napi::Number::New(env, val); +} +} + +%fragment(SWIG_AsVal_frag(double),"header") { +SWIGINTERN +int SWIG_AsVal_dec(double)(Napi::Value obj, double *val) +{ + if(!obj.IsNumber()) { + return SWIG_TypeError; + } + + if(val) { + Napi::Number num; + NAPI_CHECK_RESULT(obj.ToNumber(), num); + *val = static_cast<double>(num.DoubleValue()); + } + + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} +} diff --git a/Lib/javascript/napi/javascriptrun.swg b/Lib/javascript/napi/javascriptrun.swg new file mode 100644 index 000000000..ce698fe10 --- /dev/null +++ b/Lib/javascript/napi/javascriptrun.swg @@ -0,0 +1,446 @@ +/* --------------------------------------------------------------------------- + * Error handling + * + * ---------------------------------------------------------------------------*/ + +/* + * We support several forms: + * + * SWIG_Raise("Error message") + * which creates an Error object with the error message + * + * SWIG_Raise(SWIG_TypeError, "Type error") + * which creates the specified error type with the message + * + * SWIG_Raise(obj) + * which throws the object itself + * + * SWIG_Raise(obj, "Exception const &", SWIGType_p_Exception) + * which also throws the object itself and discards the unneeded extra type info + * + * These must be functions instead of macros to use the C++ overloading to + * resolve the arguments + */ +#define SWIG_exception(code, msg) SWIG_Error(code, msg) +#define SWIG_fail goto fail + +#ifdef NAPI_CPP_EXCEPTIONS + +#define SWIG_Error(code, msg) SWIG_NAPI_Raise(env, code, msg) +#define NAPI_CHECK_MAYBE(maybe) (maybe) +#define NAPI_CHECK_RESULT(maybe, result) (result = maybe) + +SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, const char *msg) { + throw Napi::Error::New(env, msg); +} + +SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, int type, const char *msg) { + switch(type) { + default: + case SWIG_IOError: + case SWIG_MemoryError: + case SWIG_SystemError: + case SWIG_RuntimeError: + case SWIG_DivisionByZero: + case SWIG_SyntaxError: + throw Napi::Error::New(env, msg); + case SWIG_OverflowError: + case SWIG_IndexError: + throw Napi::RangeError::New(env, msg); + case SWIG_ValueError: + case SWIG_TypeError: + throw Napi::TypeError::New(env, msg); + } +} + +SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, Napi::Value obj, + const char *msg = nullptr, swig_type_info *info = nullptr) { + throw Napi::Error(env, obj); +} + +#else + +#define SWIG_Error(code, msg) do { SWIG_NAPI_Raise(env, code, msg); SWIG_fail; } while (0) +#define NAPI_CHECK_MAYBE(maybe) do { if (maybe.IsNothing()) SWIG_fail; } while (0) +#define NAPI_CHECK_RESULT(maybe, result) \ + do { \ + auto r = maybe; \ + if (r.IsNothing()) SWIG_fail; \ + result = r.Unwrap(); \ + } while (0) + +SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, const char *msg) { + Napi::Error::New(env, msg).ThrowAsJavaScriptException(); +} + +SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, int type, const char *msg) { + switch(type) { + default: + case SWIG_IOError: + case SWIG_MemoryError: + case SWIG_SystemError: + case SWIG_RuntimeError: + case SWIG_DivisionByZero: + case SWIG_SyntaxError: + Napi::Error::New(env, msg).ThrowAsJavaScriptException(); + return; + case SWIG_OverflowError: + case SWIG_IndexError: + Napi::RangeError::New(env, msg).ThrowAsJavaScriptException(); + return; + case SWIG_ValueError: + case SWIG_TypeError: + Napi::TypeError::New(env, msg).ThrowAsJavaScriptException(); + return; + } +} + +SWIGINTERN void SWIG_NAPI_Raise(Napi::Env env, Napi::Value obj, + const char *msg = nullptr, swig_type_info *info = nullptr) { + Napi::Error(env, obj).ThrowAsJavaScriptException(); +} + +#endif + +void JS_veto_set_variable(const Napi::CallbackInfo &info) { + SWIG_NAPI_Raise(info.Env(), "Tried to write read-only variable."); +} + +struct EnvInstanceData { + Napi::Env env; + // Base class per-environment constructor, used to check + // if a JS object is a SWIG wrapper + Napi::FunctionReference *SWIG_NAPI_ObjectWrapCtor; + // Per-environment wrapper constructors, indexed by the number in + // swig_type->clientdata + Napi::FunctionReference **ctor; + swig_module_info *swig_module; + EnvInstanceData(Napi::Env, swig_module_info *); + ~EnvInstanceData(); +}; + +typedef size_t SWIG_NAPI_ClientData; + +// Base class for all wrapped objects, +// used mostly when unwrapping unknown objects +template <typename SWIG_OBJ_WRAP> +class SWIG_NAPI_ObjectWrap_templ : public Napi::ObjectWrap<SWIG_OBJ_WRAP> { + public: + void *self; + bool owned; + size_t size; + swig_type_info *info; + SWIG_NAPI_ObjectWrap_templ(const Napi::CallbackInfo &info); + SWIG_NAPI_ObjectWrap_templ(bool, const Napi::CallbackInfo &info) : + Napi::ObjectWrap<SWIG_OBJ_WRAP>(info), + self(nullptr), + owned(true), + size(0), + info(nullptr) + {} + virtual ~SWIG_NAPI_ObjectWrap_templ() {}; + + Napi::Value ToString(const Napi::CallbackInfo &info); +}; + +template <typename SWIG_OBJ_WRAP> +SWIG_NAPI_ObjectWrap_templ<SWIG_OBJ_WRAP>::SWIG_NAPI_ObjectWrap_templ(const Napi::CallbackInfo &info) : + Napi::ObjectWrap<SWIG_OBJ_WRAP>(info), size(0), info(nullptr) { + Napi::Env env = info.Env(); + if (info.Length() == 1 && info[0].IsExternal()) { + // This constructor has been called internally from C++/SWIG + // to wrap an already existing C++ object of unknown type in JS + this->self = info[0].As<Napi::External<void>>().Data(); + this->owned = false; + } else { + SWIG_Error(SWIG_ERROR, "This constructor is not accessible from JS"); + } + return; + goto fail; +fail: + return; +} + +template <typename SWIG_OBJ_WRAP> +Napi::Value SWIG_NAPI_ObjectWrap_templ<SWIG_OBJ_WRAP>::ToString(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + static char repr[128]; + const char *name = SWIG_TypePrettyName(this->info); + snprintf(repr, sizeof(repr), "{SwigObject %s (%s) at %p %s}", + this->info ? this->info->name : "unknown", + name ? name : "unknown", + this->self, + this->owned ? "[owned]" : "[copy]"); + return Napi::String::New(env, repr); +} + +class SWIG_NAPI_ObjectWrap_inst : public SWIG_NAPI_ObjectWrap_templ<SWIG_NAPI_ObjectWrap_inst> { +public: + using SWIG_NAPI_ObjectWrap_templ::SWIG_NAPI_ObjectWrap_templ; + static Napi::Function GetClass(Napi::Env); + static void GetMembers( + Napi::Env, + std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> &, + std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> & + ); +}; + +void SWIG_NAPI_ObjectWrap_inst::GetMembers( + Napi::Env env, + std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> &members, + std::map<std::string, SWIG_NAPI_ObjectWrap_templ::PropertyDescriptor> & +) { + members.erase("toString"); + members.insert({"toString", SWIG_NAPI_ObjectWrap_templ::InstanceMethod("toString", &SWIG_NAPI_ObjectWrap_templ::ToString)}); +} + +Napi::Function SWIG_NAPI_ObjectWrap_inst::GetClass(Napi::Env env) { + return Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::DefineClass(env, "SwigObject", {}); +} + +SWIGRUNTIME int SWIG_NAPI_ConvertInstancePtr(Napi::Object objRef, void **ptr, swig_type_info *info, int flags) { + SWIG_NAPI_ObjectWrap_inst *ow; + Napi::Env env = objRef.Env(); + if(!objRef.IsObject()) return SWIG_ERROR; + + // Check if this is a SWIG wrapper + Napi::FunctionReference *ctor = env.GetInstanceData<EnvInstanceData>()->SWIG_NAPI_ObjectWrapCtor; + bool instanceOf; + NAPI_CHECK_RESULT(objRef.InstanceOf(ctor->Value()), instanceOf); + if (!instanceOf) { + return SWIG_TypeError; + } + + ow = Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(objRef); + + // Now check if the SWIG type is compatible unless the types match exactly or the type is unknown + if(info && ow->info != info && ow->info != nullptr) { + swig_cast_info *tc = SWIG_TypeCheckStruct(ow->info, info); + if (!tc && ow->info->name) { + tc = SWIG_TypeCheck(ow->info->name, info); + } + bool type_valid = tc != 0; + if(!type_valid) { + return SWIG_TypeError; + } + int newmemory = 0; + *ptr = SWIG_TypeCast(tc, ow->self, &newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } else { + *ptr = ow->self; + } + + if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !ow->owned) { + return SWIG_ERROR_RELEASE_NOT_OWNED; + } else { + if (flags & SWIG_POINTER_DISOWN) { + ow->owned = false; + } + if (flags & SWIG_POINTER_CLEAR) { + ow->self = nullptr; + } + } + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} + + +SWIGRUNTIME int SWIG_NAPI_GetInstancePtr(Napi::Value valRef, void **ptr) { + SWIG_NAPI_ObjectWrap_inst *ow; + if(!valRef.IsObject()) { + return SWIG_TypeError; + } + Napi::Object objRef; + NAPI_CHECK_RESULT(valRef.ToObject(), objRef); + ow = Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(objRef); + + if(ow->self == nullptr) { + return SWIG_ERROR; + } + + *ptr = ow->self; + return SWIG_OK; + goto fail; +fail: + return SWIG_ERROR; +} + + +SWIGRUNTIME int SWIG_NAPI_ConvertPtr(Napi::Value valRef, void **ptr, swig_type_info *info, int flags) { + // special case: JavaScript null => C NULL pointer + if (valRef.IsNull()) { + *ptr=0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; + } + + if (!valRef.IsObject()) { + return SWIG_TypeError; + } + + Napi::Object objRef; + NAPI_CHECK_RESULT(valRef.ToObject(), objRef); + return SWIG_NAPI_ConvertInstancePtr(objRef, ptr, info, flags); + goto fail; +fail: + return SWIG_ERROR; +} + +SWIGRUNTIME Napi::Value SWIG_NAPI_NewPointerObj(Napi::Env env, void *ptr, swig_type_info *info, int flags) { + Napi::External<void> native; + Napi::FunctionReference *ctor; + + if (ptr == nullptr) { + return env.Null(); + } + native = Napi::External<void>::New(env, ptr); + + size_t *idx = info != nullptr ? + reinterpret_cast<SWIG_NAPI_ClientData *>(info->clientdata) : + nullptr; + if (idx == nullptr) { + // This type does not have a dedicated wrapper + ctor = env.GetInstanceData<EnvInstanceData>()->SWIG_NAPI_ObjectWrapCtor; + } else { + ctor = env.GetInstanceData<EnvInstanceData>()->ctor[*idx]; + } + + Napi::Value wrapped; + NAPI_CHECK_RESULT(ctor->New({native}), wrapped); + + // Preserve the type even if using the generic wrapper + if (idx == nullptr && info != nullptr) { + Napi::Object obj; + NAPI_CHECK_RESULT(wrapped.ToObject(), obj); + Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(obj)->info = info; + } + + if ((flags & SWIG_POINTER_OWN) == SWIG_POINTER_OWN) { + Napi::Object obj; + NAPI_CHECK_RESULT(wrapped.ToObject(), obj); + Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(obj)->owned = true; + } + + return wrapped; + goto fail; +fail: + return Napi::Value(); +} + +#define SWIG_ConvertPtr(obj, ptr, info, flags) SWIG_NAPI_ConvertPtr(obj, ptr, info, flags) +#define SWIG_NewPointerObj(ptr, info, flags) SWIG_NAPI_NewPointerObj(env, ptr, info, flags) + +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_NAPI_ConvertInstancePtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(thisvalue, type, flags) SWIG_NAPI_NewPointerObj(env, thisvalue, type, flags) + +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_NAPI_ConvertPtr(obj, pptr, type, 0) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_NAPI_NewPointerObj(env, ptr, type, 0) + +#define SWIG_GetInstancePtr(obj, ptr) SWIG_NAPI_GetInstancePtr(obj, ptr) + +SWIGRUNTIME Napi::Value _SWIG_NAPI_wrap_equals(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + void *arg1 = (void *) 0 ; + void *arg2 = (void *) 0 ; + bool result; + int res1; + int res2; + + if(info.Length() != 1) SWIG_Error(SWIG_ERROR, "Illegal number of arguments for equals."); + + res1 = SWIG_GetInstancePtr(info.This(), &arg1); + if (!SWIG_IsOK(res1)) { + SWIG_Error(SWIG_ERROR, "Could not get pointer from 'this' object for equals."); + } + res2 = SWIG_GetInstancePtr(info[0], &arg2); + if (!SWIG_IsOK(res2)) { + SWIG_Error(SWIG_ArgError(res2), " in method '" "equals" "', argument " "1"" of type '" "void *""'"); + } + + result = (bool)(arg1 == arg2); + jsresult = Napi::Boolean::New(env, result); + + return jsresult; + goto fail; +fail: + return Napi::Value(); +} + +SWIGRUNTIME Napi::Value _wrap_getCPtr(const Napi::CallbackInfo &info) { + Napi::Env env = info.Env(); + Napi::Value jsresult; + void *arg1 = (void *) 0 ; + long result; + int res1; + + res1 = SWIG_GetInstancePtr(info.This(), &arg1); + if (!SWIG_IsOK(res1)) { + SWIG_Error(SWIG_ArgError(res1), " in method '" "getCPtr" "', argument " "1"" of type '" "void *""'"); + } + + result = (long)arg1; + jsresult = Napi::Number::New(env, result); + + return jsresult; + goto fail; +fail: + return Napi::Value(); +} + + +/* --------------------------------------------------------------------------- + * PackedData object + * (objects visible to JS that do not have a dedicated wrapper but must preserve type) + * ---------------------------------------------------------------------------*/ + +SWIGRUNTIME +Napi::Value SWIG_NAPI_NewPackedObj(Napi::Env env, void *data, size_t size, swig_type_info *type) { + void *data_copy = new uint8_t[size]; + memcpy(data_copy, data, size); + Napi::Value val = SWIG_NAPI_NewPointerObj(env, data_copy, type, SWIG_POINTER_OWN); + Napi::Object obj; + if (val.IsEmpty()) goto fail; + + NAPI_CHECK_RESULT(val.ToObject(), obj); + Napi::ObjectWrap<SWIG_NAPI_ObjectWrap_inst>::Unwrap(obj)->size = size; + +fail: + return val; +} + +SWIGRUNTIME +int SWIG_NAPI_ConvertPacked(Napi::Value valRef, void *ptr, size_t size, swig_type_info *type) { + void *tmp; + if (!SWIG_IsOK(SWIG_NAPI_ConvertPtr(valRef, &tmp, type, 0))) { + return SWIG_ERROR; + } + memcpy(ptr, tmp, size); + return SWIG_OK; +} + +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_NAPI_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_NAPI_NewPackedObj(env, ptr, sz, type) + + +/* --------------------------------------------------------------------------- + * Support for IN/OUTPUT typemaps (see Lib/typemaps/inoutlist.swg) + * + * ---------------------------------------------------------------------------*/ + +SWIGRUNTIME + +Napi::Value SWIG_NAPI_AppendOutput(Napi::Env env, Napi::Value result, Napi::Value obj) { + if (result.IsUndefined()) { + result = Napi::Array::New(env); + } else if (!result.IsArray()) { + Napi::Array tmparr = Napi::Array::New(env); + tmparr.Set(static_cast<uint32_t>(0), result); + result = tmparr; + } + + Napi::Array arr = result.As<Napi::Array>(); + arr.Set(arr.Length(), obj); + return arr; +} diff --git a/Lib/javascript/napi/javascriptruntime.swg b/Lib/javascript/napi/javascriptruntime.swg new file mode 100644 index 000000000..42f11ed8c --- /dev/null +++ b/Lib/javascript/napi/javascriptruntime.swg @@ -0,0 +1,40 @@ +/* ----------------------------------------------------------------------------- + * javascriptruntime.swg + * + * ----------------------------------------------------------------------------- */ + +// NAPI +// ---------- + +%insert(runtime) %{ +#if defined(_CPPUNWIND) || defined(__EXCEPTIONS) +#define NAPI_CPP_EXCEPTIONS +#else +#define NAPI_DISABLE_CPP_EXCEPTIONS +#define NODE_ADDON_API_ENABLE_MAYBE +#endif + +// This gives us +// Branch Node.js v10.x - from v10.20.0 +// Branch Node.js v12.x - from v12.17.0 +// Everything from Node.js v14.0.0 on +// Our limiting feature is napi_set_instance_data +#ifndef NAPI_VERSION +#define NAPI_VERSION 6 +#elif NAPI_VERSION < 6 +#error NAPI_VERSION 6 is the minimum supported target (Node.js >=14, >=12.17, >=10.20) +#endif +#include <napi.h> + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <assert.h> +#include <map> +%} + +%insert(runtime) "swigrun.swg"; /* SWIG API */ +%insert(runtime) "swigerrors.swg"; /* SWIG errors */ + +%insert(runtime) "javascriptrun.swg" + diff --git a/Lib/javascript/napi/javascriptstrings.swg b/Lib/javascript/napi/javascriptstrings.swg new file mode 100644 index 000000000..7293c7b0f --- /dev/null +++ b/Lib/javascript/napi/javascriptstrings.swg @@ -0,0 +1,77 @@ + +/* ------------------------------------------------------------ + * utility methods for char strings + * ------------------------------------------------------------ */ +%fragment("SWIG_AsCharPtrAndSize", "header", fragment="SWIG_pchar_descriptor") { +SWIGINTERN int +SWIG_AsCharPtrAndSize(Napi::Value valRef, char** cptr, size_t* psize, int *alloc) +{ + if(valRef.IsString()) { + Napi::String js_str; + NAPI_CHECK_RESULT(valRef.ToString(), js_str); + + std::string str = js_str.Utf8Value(); + size_t len = str.size() + 1; + char* cstr = (char*) %new_array(len, char); + memcpy(cstr, str.data(), len); + + if(alloc) *alloc = SWIG_NEWOBJ; + if(psize) *psize = len; + if(cptr) *cptr = cstr; + + return SWIG_OK; + } else { + if(valRef.IsObject()) { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + Napi::Object obj; + NAPI_CHECK_RESULT(valRef.ToObject(), obj); + // try if the object is a wrapped char[] + if (pchar_descriptor) { + void* vptr = 0; + if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = (char *) vptr; + if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + } + goto fail; +fail: + return SWIG_TypeError; +} +} + + +%fragment(SWIG_From_frag(char), "header") { +SWIGINTERNINLINE Napi::Value +SWIG_From_char(Napi::Env env, char c) +{ + Napi::String js_str = Napi::String::New(env, &c, 1); + return js_str; +} +} + + +%fragment("SWIG_FromCharPtr", "header", fragment = "SWIG_FromCharPtrAndSize") { +// Override the default one with an empty one +} + +%fragment("SWIG_FromCharPtrAndSize", "header") { +SWIGINTERNINLINE Napi::Value +SWIG_Env_FromCharPtrAndSize(Napi::Env env, const char* carray, size_t size) +{ + if (carray) { + Napi::String js_str = Napi::String::New(env, carray, size); + return js_str; + } else { + return env.Undefined(); + } +} +} + +%insert(runtime) %{ +#define SWIG_FromCharPtrAndSize(cptr, size) SWIG_Env_FromCharPtrAndSize(env, cptr, size) +#define SWIG_FromCharPtr(cptr) SWIG_Env_FromCharPtrAndSize(env, cptr, strlen(cptr)) +%} diff --git a/Lib/javascript/napi/javascripttypemaps.swg b/Lib/javascript/napi/javascripttypemaps.swg new file mode 100644 index 000000000..d7d21be2e --- /dev/null +++ b/Lib/javascript/napi/javascripttypemaps.swg @@ -0,0 +1,56 @@ +/* ------------------------------------------------------------ + * Typemap specializations for Javascript + * ------------------------------------------------------------ */ + +/* ------------------------------------------------------------ + * Fragment section + * ------------------------------------------------------------ */ + +/* These macros are necessary to provide an extra parameter + to SWIG_AsVal_dec functions (Napi::Env environment). + They must be defined before including `typemaps/fragments.swg` +*/ +#define SWIG_FROM_DECL_ARGS SWIG_NAPI_FROM_DECL_ARGS +#define SWIG_FROM_CALL_ARGS SWIG_NAPI_FROM_CALL_ARGS + +/* Include fundamental fragemt definitions */ +%include <typemaps/fragments.swg> + +/* Look for user fragments file. */ +%include <javascriptfragments.swg> + +/* Javascript fragments for fundamental types */ +%include <javascriptprimtypes.swg> + +/* Javascript fragments for char* strings */ +%include <javascriptstrings.swg> + + +/* ------------------------------------------------------------ + * Unified typemap section + * ------------------------------------------------------------ */ + +/* Javascript types */ + +#define SWIG_Object Napi::Value +#define VOID_Object env.Undefined() + +/* Overload of the output/constant/exception/dirout handling */ + +/* append output */ +#define SWIG_AppendOutput(result, obj) SWIG_NAPI_AppendOutput(env, result, obj) + +/* set constant */ +#define SWIG_SetConstant(name, obj) + +/* raise */ +#define SWIG_Raise(...) SWIG_NAPI_Raise(env, __VA_ARGS__) + +%insert("runtime") %{ +#define SWIG_NAPI_FROM_DECL_ARGS(arg1) (Napi::Env env, arg1) +#define SWIG_NAPI_FROM_CALL_ARGS(arg1) (env, arg1) +%} + + +/* Include the unified typemap library */ +%include <typemaps/swigtypemaps.swg> diff --git a/Lib/javascript/napi/nodejs_buffer.i b/Lib/javascript/napi/nodejs_buffer.i new file mode 100644 index 000000000..d95ba2d65 --- /dev/null +++ b/Lib/javascript/napi/nodejs_buffer.i @@ -0,0 +1,47 @@ +/* + * To include generic versions of the in typemaps, add: + * + * %typemap(in) (void *, size_t) = (const void* buffer_data, const size_t buffer_len); + * %typemap(typecheck) (void *, size_t) = (const void* buffer_data, const size_t buffer_len); + * + * or to discriminate by argument names: + * %typemap(in) (void *data, size_t length) = (const void* buffer_data, const size_t buffer_len); + * %typemap(typecheck) (void *data, size_t length) = (const void* buffer_data, const size_t buffer_len); + */ + +%typemap(in) (const void* buffer_data, const size_t buffer_len) { + if ($input.IsBuffer()) { + Napi::Buffer<char> buf = $input.As<Napi::Buffer<char>>(); + $1 = reinterpret_cast<void *>(buf.Data()); + $2 = buf.ByteLength(); + } else { + SWIG_exception_fail(SWIG_TypeError, "in method '$symname', argument is not a Buffer"); + } +} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_VOIDPTR) (const void* buffer_data, const size_t buffer_len) { + $1 = $input.IsBuffer(); +} + + +/* + * In order to use the argout typemap, the function must have the following signature: + * + * void buffer(void **buffer_data, size_t *buffer_len) + * + * In this case, this function will be wrapped by a JS function that takes + * no arguments (because of numinputs=0) and returns a Buffer + */ + +%typemap(in, numinputs=0) (void **buffer_data, size_t *buffer_len) (void *temp_data, size_t temp_len) { + $1 = &temp_data; + $2 = &temp_len; +} +%typemap(argout) (void **buffer_data, size_t *buffer_len) { + if (*$1 != nullptr) { + Napi::Buffer<char> buf = Napi::Buffer<char>::Copy(env, reinterpret_cast<char *>(*$1), *$2); + NAPI_CHECK_RESULT(buf.As<Napi::Value>(), $result); + } else { + $result = env.Null(); + } +} diff --git a/Lib/javascript/napi/std_auto_ptr.i b/Lib/javascript/napi/std_auto_ptr.i new file mode 100644 index 000000000..3d7ae8ba1 --- /dev/null +++ b/Lib/javascript/napi/std_auto_ptr.i @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------- + * std_auto_ptr.i + * + * SWIG library file for handling std::auto_ptr. + * Memory ownership is passed from the std::auto_ptr C++ layer to the proxy + * class when returning a std::auto_ptr from a function. + * Memory ownership is passed from the proxy class to the std::auto_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %auto_ptr(TYPE) +%typemap(in, noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::auto_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::auto_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + +%template() std::auto_ptr< TYPE >; +%enddef + +namespace std { + template <class T> class auto_ptr {}; +} diff --git a/Lib/javascript/napi/std_common.i b/Lib/javascript/napi/std_common.i new file mode 100644 index 000000000..cee11e8ca --- /dev/null +++ b/Lib/javascript/napi/std_common.i @@ -0,0 +1,5 @@ +%include <std_except.i> + +%apply size_t { std::size_t }; +%apply const size_t& { const std::size_t& }; + diff --git a/Lib/javascript/napi/std_complex.i b/Lib/javascript/napi/std_complex.i new file mode 100644 index 000000000..a252e0aa8 --- /dev/null +++ b/Lib/javascript/napi/std_complex.i @@ -0,0 +1,26 @@ +/* + * STD C++ complex typemaps + */ + +%include <javascriptcomplex.swg> + +%{ +#include <complex> +%} + +namespace std { + %naturalvar complex; + template<typename T> class complex; + %template() complex<double>; + %template() complex<float>; +} + +/* defining the complex as/from converters */ + +%swig_cplxdbl_convn(std::complex<double>, std::complex<double>, std::real, std::imag) +%swig_cplxflt_convn(std::complex<float>, std::complex<float>, std::real, std::imag) + +/* defining the typemaps */ + +%typemaps_primitive(%checkcode(CPLXDBL), std::complex<double>); +%typemaps_primitive(%checkcode(CPLXFLT), std::complex<float>); diff --git a/Lib/javascript/napi/std_deque.i b/Lib/javascript/napi/std_deque.i new file mode 100644 index 000000000..cb98f6c2f --- /dev/null +++ b/Lib/javascript/napi/std_deque.i @@ -0,0 +1 @@ +%include <std/_std_deque.i> diff --git a/Lib/javascript/napi/std_except.i b/Lib/javascript/napi/std_except.i new file mode 100644 index 000000000..af98428f6 --- /dev/null +++ b/Lib/javascript/napi/std_except.i @@ -0,0 +1 @@ +%include <typemaps/std_except.swg> diff --git a/Lib/javascript/napi/std_map.i b/Lib/javascript/napi/std_map.i new file mode 100644 index 000000000..a33e88683 --- /dev/null +++ b/Lib/javascript/napi/std_map.i @@ -0,0 +1,71 @@ +/* ----------------------------------------------------------------------------- + * std_map.i + * + * SWIG typemaps for std::map + * ----------------------------------------------------------------------------- */ + +%include <std_common.i> + +// ------------------------------------------------------------------------ +// std::map +// ------------------------------------------------------------------------ + +%{ +#include <map> +#include <algorithm> +#include <stdexcept> +%} + +// exported class + +namespace std { + + template<class K, class T, class C = std::less<K> > class map { + // add typemaps here + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef K key_type; + typedef T mapped_type; + typedef std::pair< const K, T > value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + map(); + map(const map& other); + + unsigned int size() const; + bool empty() const; + void clear(); + %extend { + const T& get(const K& key) throw (std::out_of_range) { + std::map< K, T, C >::iterator i = self->find(key); + if (i != self->end()) + return i->second; + else + throw std::out_of_range("key not found"); + } + void set(const K& key, const T& x) { +%#ifdef __cpp_lib_map_try_emplace + (*self).insert_or_assign(key, x); +%#else + (*self)[key] = x; +%#endif + } + void del(const K& key) throw (std::out_of_range) { + std::map< K, T, C >::iterator i = self->find(key); + if (i != self->end()) + self->erase(i); + else + throw std::out_of_range("key not found"); + } + bool has_key(const K& key) { + std::map< K, T, C >::iterator i = self->find(key); + return i != self->end(); + } + } + }; + +} diff --git a/Lib/javascript/napi/std_pair.i b/Lib/javascript/napi/std_pair.i new file mode 100644 index 000000000..b72c50b99 --- /dev/null +++ b/Lib/javascript/napi/std_pair.i @@ -0,0 +1,35 @@ +/* ----------------------------------------------------------------------------- + * std_pair.i + * + * SWIG typemaps for std::pair + * ----------------------------------------------------------------------------- */ + +%include <std_common.i> + +// ------------------------------------------------------------------------ +// std::pair +// ------------------------------------------------------------------------ + +%{ +#include <utility> +%} + +namespace std { + + template<class T, class U> struct pair { + typedef T first_type; + typedef U second_type; + + pair(); + pair(T first, U second); + pair(const pair& other); + + template <class U1, class U2> pair(const pair<U1, U2> &other); + + T first; + U second; + }; + + // add specializations here + +} diff --git a/Lib/javascript/napi/std_string.i b/Lib/javascript/napi/std_string.i new file mode 100644 index 000000000..dc1378ae6 --- /dev/null +++ b/Lib/javascript/napi/std_string.i @@ -0,0 +1 @@ +%include <typemaps/std_string.swg> diff --git a/Lib/javascript/napi/std_unique_ptr.i b/Lib/javascript/napi/std_unique_ptr.i new file mode 100644 index 000000000..f988714df --- /dev/null +++ b/Lib/javascript/napi/std_unique_ptr.i @@ -0,0 +1,39 @@ +/* ----------------------------------------------------------------------------- + * std_unique_ptr.i + * + * SWIG library file for handling std::unique_ptr. + * Memory ownership is passed from the std::unique_ptr C++ layer to the proxy + * class when returning a std::unique_ptr from a function. + * Memory ownership is passed from the proxy class to the std::unique_ptr in the + * C++ layer when passed as a parameter to a wrapped function. + * ----------------------------------------------------------------------------- */ + +%define %unique_ptr(TYPE) +%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) { + res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags); + if (!SWIG_IsOK(res)) { + if (res == SWIG_ERROR_RELEASE_NOT_OWNED) { + %releasenotowned_fail(res, "TYPE *", $symname, $argnum); + } else { + %argument_fail(res, "TYPE *", $symname, $argnum); + } + } + $1.reset((TYPE *)argp); +} + +%typemap (out) std::unique_ptr< TYPE > %{ + %set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags)); +%} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_POINTER, equivalent="TYPE *", noblock=1) std::unique_ptr< TYPE > { + void *vptr = 0; + int res = SWIG_ConvertPtr($input, &vptr, $descriptor(TYPE *), 0); + $1 = SWIG_CheckState(res); +} + +%template() std::unique_ptr< TYPE >; +%enddef + +namespace std { + template <class T> class unique_ptr {}; +} diff --git a/Lib/javascript/napi/std_vector.i b/Lib/javascript/napi/std_vector.i new file mode 100644 index 000000000..586ac5c60 --- /dev/null +++ b/Lib/javascript/napi/std_vector.i @@ -0,0 +1,99 @@ +/* ----------------------------------------------------------------------------- + * std_vector.i + * ----------------------------------------------------------------------------- */ + +%include <std_common.i> + +%{ +#include <vector> +#include <stdexcept> +%} + +namespace std { + + template<class T> class vector { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + vector(); + vector(size_type n); + vector(const vector& other); + + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %rename(add) push_back; + void push_back(const value_type& x); + %extend { + const_reference get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && i<size) + return (*self)[i]; + else + throw std::out_of_range("vector index out of range"); + } + void set(int i, const value_type& val) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && i<size) + (*self)[i] = val; + else + throw std::out_of_range("vector index out of range"); + } + } + }; + + // bool specialization + template<> class vector<bool> { + public: + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef bool value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef bool const_reference; + + vector(); + vector(size_type n); + vector(const vector& other); + + size_type size() const; + size_type capacity() const; + void reserve(size_type n); + %rename(isEmpty) empty; + bool empty() const; + void clear(); + %rename(add) push_back; + void push_back(const value_type& x); + %extend { + bool get(int i) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && i<size) + return (*self)[i]; + else + throw std::out_of_range("vector index out of range"); + } + void set(int i, const value_type& val) throw (std::out_of_range) { + int size = int(self->size()); + if (i>=0 && i<size) + (*self)[i] = val; + else + throw std::out_of_range("vector index out of range"); + } + } + }; +} + +%define specialize_std_vector(T) +#warning "specialize_std_vector - specialization for type T no longer needed" +%enddef + diff --git a/Lib/javascript/napi/stl.i b/Lib/javascript/napi/stl.i new file mode 100644 index 000000000..04f86014f --- /dev/null +++ b/Lib/javascript/napi/stl.i @@ -0,0 +1,10 @@ +/* ----------------------------------------------------------------------------- + * stl.i + * ----------------------------------------------------------------------------- */ + +%include <std_common.i> +%include <std_string.i> +%include <std_vector.i> +%include <std_map.i> +%include <std_pair.i> + diff --git a/Lib/javascript/napi/swigmove.i b/Lib/javascript/napi/swigmove.i new file mode 100644 index 000000000..62ecca768 --- /dev/null +++ b/Lib/javascript/napi/swigmove.i @@ -0,0 +1 @@ +%include <typemaps/swigmove.swg> diff --git a/Lib/javascript/napi/typemaps.i b/Lib/javascript/napi/typemaps.i new file mode 100644 index 000000000..08b583863 --- /dev/null +++ b/Lib/javascript/napi/typemaps.i @@ -0,0 +1,144 @@ +/* ----------------------------------------------------------------------------- + * typemaps.i + * + * Pointer handling + * These mappings provide support for input/output arguments and common + * uses for C/C++ pointers. + * ----------------------------------------------------------------------------- */ + +// INPUT typemaps. +// These remap a C pointer to be an "INPUT" value which is passed by value +// instead of reference. + +/* +The following methods can be applied to turn a pointer into a simple +"input" value. That is, instead of passing a pointer to an object, +you would use a real value instead. + + int *INPUT + short *INPUT + long *INPUT + long long *INPUT + unsigned int *INPUT + unsigned short *INPUT + unsigned long *INPUT + unsigned long long *INPUT + unsigned char *INPUT + bool *INPUT + float *INPUT + double *INPUT + +To use these, suppose you had a C function like this : + + double fadd(double *a, double *b) { + return *a+*b; + } + +You could wrap it with SWIG as follows : + + %include <typemaps.i> + double fadd(double *INPUT, double *INPUT); + +or you can use the %apply directive : + + %include <typemaps.i> + %apply double *INPUT { double *a, double *b }; + double fadd(double *a, double *b); + +*/ + +// OUTPUT typemaps. These typemaps are used for parameters that +// are output only. The output value is appended to the result as +// a list element. + +/* +The following methods can be applied to turn a pointer into an "output" +value. When calling a function, no input value would be given for +a parameter, but an output value would be returned. In the case of +multiple output values, they are returned in the form of a Python tuple. + + int *OUTPUT + short *OUTPUT + long *OUTPUT + long long *OUTPUT + unsigned int *OUTPUT + unsigned short *OUTPUT + unsigned long *OUTPUT + unsigned long long *OUTPUT + unsigned char *OUTPUT + bool *OUTPUT + float *OUTPUT + double *OUTPUT + +For example, suppose you were trying to wrap the modf() function in the +C math library which splits x into integral and fractional parts (and +returns the integer part in one of its parameters) : + + double modf(double x, double *ip); + +You could wrap it with SWIG as follows : + + %include <typemaps.i> + double modf(double x, double *OUTPUT); + +or you can use the %apply directive : + + %include <typemaps.i> + %apply double *OUTPUT { double *ip }; + double modf(double x, double *ip); + +The Python output of the function would be a tuple containing both +output values. + +*/ + +// INOUT +// Mappings for an argument that is both an input and output +// parameter + +/* +The following methods can be applied to make a function parameter both +an input and output value. This combines the behavior of both the +"INPUT" and "OUTPUT" methods described earlier. Output values are +returned in the form of a Python tuple. + + int *INOUT + short *INOUT + long *INOUT + long long *INOUT + unsigned int *INOUT + unsigned short *INOUT + unsigned long *INOUT + unsigned long long *INOUT + unsigned char *INOUT + bool *INOUT + float *INOUT + double *INOUT + +For example, suppose you were trying to wrap the following function : + + void neg(double *x) { + *x = -(*x); + } + +You could wrap it with SWIG as follows : + + %include <typemaps.i> + void neg(double *INOUT); + +or you can use the %apply directive : + + %include <typemaps.i> + %apply double *INOUT { double *x }; + void neg(double *x); + +Unlike C, this mapping does not directly modify the input value (since +this makes no sense in Python). Rather, the modified input value shows +up as the return value of the function. Thus, to apply this function +to a Python variable you might do this : + + x = neg(x) + +*/ + +%include <typemaps/typemaps.swg> |