diff options
author | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2021-01-28 22:45:57 -0500 |
---|---|---|
committer | Jonathan Buchanan <jonathan.russ.buchanan@gmail.com> | 2021-01-28 22:45:57 -0500 |
commit | 43a8d866a4703aac8c545562eb8e2d3a610c4f68 (patch) | |
tree | 2dcaf6be0cec33065860262f1cc209387de45ed0 /Taler | |
parent | 97b916f0c1baeb2d931bb9457b0f2e8b966c4964 (diff) | |
download | taler-ios-43a8d866a4703aac8c545562eb8e2d3a610c4f68.tar.gz taler-ios-43a8d866a4703aac8c545562eb8e2d3a610c4f68.tar.bz2 taler-ios-43a8d866a4703aac8c545562eb8e2d3a610c4f68.zip |
add node to swift/objc bridge
Diffstat (limited to 'Taler')
-rw-r--r-- | Taler/AppDelegate.swift | 6 | ||||
-rw-r--r-- | Taler/NodeWrapper.swift | 49 | ||||
-rw-r--r-- | Taler/Taler-Bridging-Header.h | 4 | ||||
-rw-r--r-- | Taler/node_wrapper.cpp | 274 | ||||
-rw-r--r-- | Taler/node_wrapper.h | 44 |
5 files changed, 374 insertions, 3 deletions
diff --git a/Taler/AppDelegate.swift b/Taler/AppDelegate.swift index ab96d31..e5e6bcd 100644 --- a/Taler/AppDelegate.swift +++ b/Taler/AppDelegate.swift @@ -7,7 +7,6 @@ // import UIKit -import TalerWallet @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { @@ -16,8 +15,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. - let num = Amount.init(currency: "EUR", value: 1, fraction: 99) - print(num) + var iono = Iono(); + print(iono.evalJS(source: "1 + 1")) + iono.evalJS(source: "console.log(\"test!\");"); return true } diff --git a/Taler/NodeWrapper.swift b/Taler/NodeWrapper.swift new file mode 100644 index 0000000..60ca92b --- /dev/null +++ b/Taler/NodeWrapper.swift @@ -0,0 +1,49 @@ +// +// NodeWrapper.swift +// Taler +// +// Created by Jonathan Buchanan on 1/14/21. +// Copyright © 2021 Taler. All rights reserved. +// + +import Foundation + +class Iono { + var __instance: OpaquePointer + var messageHandler: ((String) -> ())? + + init() { + __instance = __new_instance() + } + + deinit { + __free_instance(__instance) + } + + func notifyNative() { + + } + + func evalJS(source: String) -> String { + var result_cstr: UnsafeMutablePointer<Int8> = __eval_js(source.cString(using: .utf8), __instance) + var result = String(cString: result_cstr) + free(result_cstr) + return result + } + + func evalNodeCode(source: String) { + __make_callback(source.cString(using: .utf8), __instance) + } + + func sendMessage(message: String) { + + } + + func waitUntilStopped() { + + } + + func putModuleCode(moduleName: String, code: String) { + __put_module_code(moduleName.cString(using: .utf8), code.cString(using: .utf8), __instance) + } +} diff --git a/Taler/Taler-Bridging-Header.h b/Taler/Taler-Bridging-Header.h new file mode 100644 index 0000000..f4a0414 --- /dev/null +++ b/Taler/Taler-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// +#import "node_wrapper.h" diff --git a/Taler/node_wrapper.cpp b/Taler/node_wrapper.cpp new file mode 100644 index 0000000..7899281 --- /dev/null +++ b/Taler/node_wrapper.cpp @@ -0,0 +1,274 @@ +// +// node_wrapper.cpp +// Taler +// +// Created by Jonathan Buchanan on 12/31/20. +// Copyright © 2020 Taler. All rights reserved. +// + +#include <map> +#include <string> + +#include "node.h" +#include "uv.h" + +struct __IonoInstance +{ + static std::unique_ptr<node::MultiIsolatePlatform> platform; + std::unique_ptr<node::CommonEnvironmentSetup> setup; + v8::Isolate *isolate; + node::Environment *env; + uv_async_t async_notify; + bool break_requested; + std::map<std::string, std::string> modmap; + + __IonoInstance(); + + char * + eval_js(const char *js); + + void + run_node(); + + void + make_callback(const char *callback); +}; + +#ifdef __cplusplus +extern "C" { +#endif + +struct __IonoInstance * +__new_instance() +{ + __IonoInstance *instance = new __IonoInstance(); + return instance; +} + +void +__free_instance(struct __IonoInstance *instance) +{ + delete instance; +} + +char * +__eval_js(const char *js, struct __IonoInstance *instance) +{ + return instance->eval_js(js); +} + +void +__notify_instance(struct __IonoInstance *instance) +{ + uv_async_send(&instance->async_notify); +} + +void +__run_node(struct __IonoInstance *instance) +{ + instance->run_node(); +} + +void +__make_callback(const char *callback, struct __IonoInstance *instance) +{ + instance->make_callback(callback); +} + +void +__put_module_code(const char *module_name, const char *module_code, struct __IonoInstance *instance) +{ + instance->modmap[std::string(module_name)] = std::string(module_code); +} + +#ifdef __cplusplus +} +#endif + +std::unique_ptr<node::MultiIsolatePlatform> __IonoInstance::platform = nullptr; + +static void +notify_callback(uv_async_t *async); + +static void +send_message_callback(const v8::FunctionCallbackInfo<v8::Value> &args); + +__IonoInstance::__IonoInstance() : + break_requested(false), + modmap() +{ + { + uv_loop_t *loop = uv_default_loop(); + uv_async_init(loop, &async_notify, ¬ify_callback); + async_notify.data = this; + } + + std::vector<std::string> args = { "node" }; + std::vector<std::string> exec_args; + std::vector<std::string> errors; + + if (nullptr == platform) + { + int exit_code = node::InitializeNodeWithArgs(&args, &exec_args, &errors); + for (const std::string &error : errors) + { + fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str()); + /*if (exit_code != 0) { + return exit_code;*/ + } + + platform = node::MultiIsolatePlatform::Create(4); + v8::V8::InitializePlatform(platform.get()); + v8::V8::Initialize(); + } + + setup = node::CommonEnvironmentSetup::Create(platform.get(), &errors, args, exec_args); + if (!setup) { + for (const std::string &err : errors) + fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str()); + //return 1; + } + + isolate = setup->isolate(); + env = setup->env(); + + { + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(setup->context()); + + v8::MaybeLocal<v8::Value> loadenv_ret = node::LoadEnvironment( + env, + "const publicRequire =" + " require('module').createRequire(process.cwd() + '/');" + "globalThis.require = publicRequire;" + "global.__node_run = (x) => {" + " 0 && console.log('running code', x);" + " global.eval(x);" + "};"); + + v8::Local<v8::ObjectTemplate> data_template = v8::ObjectTemplate::New(isolate); + data_template->SetInternalFieldCount(1); + v8::Local<v8::Object> data_object = data_template->NewInstance(setup->context()).ToLocalChecked(); + data_object->SetAlignedPointerInInternalField(0, this); + + v8::Local<v8::Function> sendMessageFunction = v8::Function::New(setup->context(), + send_message_callback, + data_object).ToLocalChecked(); + + v8::Local<v8::Object> global = setup->context()->Global(); + + global->Set(setup->context(), v8::String::NewFromUtf8(isolate, "__iono_sendMessage", + v8::NewStringType::kNormal).ToLocalChecked(), + sendMessageFunction).Check(); + } +} + +char * +__IonoInstance::eval_js(const char *js) +{ + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(setup->context()); + + { + // Create a string containing the JavaScript source code. + v8::Local<v8::String> source = + v8::String::NewFromUtf8(isolate, js, v8::NewStringType::kNormal).ToLocalChecked(); + + // Compile the source code. + v8::Local<v8::Script> script; + + if (!v8::Script::Compile(setup->context(), source).ToLocal(&script)) { + return nullptr; + } + + // Run the script to get the result. + v8::Local<v8::Value> result; + if (!script->Run(setup->context()).ToLocal(&result)) { + return nullptr; + } + + // Convert the result to an UTF8 string and print it. + v8::String::Utf8Value utf8(isolate, result); + + return strdup(*utf8); + } +} + +void +__IonoInstance::run_node() { + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(setup->context()); + break_requested = false; + while (true) { + uv_run(uv_default_loop(), UV_RUN_ONCE); + platform->DrainTasks(isolate); + if (break_requested) + break; + } +} + +void +__IonoInstance::make_callback(const char *callback) +{ + v8::Locker locker(isolate); + v8::Isolate::Scope isolate_scope(isolate); + v8::HandleScope handle_scope(isolate); + v8::Context::Scope context_scope(setup->context()); + v8::Local<v8::Object> global = setup->context()->Global(); + v8::Local<v8::Value> argv[] = { + v8::String::NewFromUtf8(isolate, callback, + v8::NewStringType::kNormal).ToLocalChecked() + }; + node::MakeCallback(isolate, global, "__node_run", 1, argv, {0, 0}); +} + +static void +notify_callback(uv_async_t *async) { + __IonoInstance *instance = (__IonoInstance *)async->data; + instance->break_requested = true; +} + +static void +send_message_callback(const v8::FunctionCallbackInfo<v8::Value> &args) { + v8::Isolate *isolate = args.GetIsolate(); + v8::Locker locker(isolate); + if (args.Length() < 1) return; + v8::HandleScope scope(isolate); + v8::Local<v8::Value> arg = args[0]; + v8::String::Utf8Value value(isolate, arg); + + v8::Local<v8::Object> data = v8::Local<v8::Object>::Cast(args.Data()); + + __IonoInstance *instance = (__IonoInstance *)data->GetAlignedPointerFromInternalField(0); + + /*JNIEnv *env = myInstance->currentJniEnv; + + if (env == nullptr) { + mylog("FATAL: JNI env is nullptr"); + return; + } + + jclass clazz = env->FindClass("akono/AkonoJni"); + + if (clazz == nullptr) { + mylog("FATAL: class not found"); + return; + } + + jstring payloadStr = env->NewStringUTF(*value); + + jmethodID meth = env->GetMethodID(clazz, "internalOnNotify", "(Ljava/lang/String;)V"); + + if (meth == nullptr) { + mylog("FATAL: method not found"); + return; + } + + env->CallVoidMethod(myInstance->currentJniThiz, meth, payloadStr);*/ +} diff --git a/Taler/node_wrapper.h b/Taler/node_wrapper.h new file mode 100644 index 0000000..164b95e --- /dev/null +++ b/Taler/node_wrapper.h @@ -0,0 +1,44 @@ +// +// node_wrapper.h +// Taler +// +// Created by Jonathan Buchanan on 12/31/20. +// Copyright © 2020 Taler. All rights reserved. +// + +#ifndef node_wrapper_h +#define node_wrapper_h + +#ifdef __cplusplus +extern "C" { +#endif + +struct __IonoInstance; + +struct __IonoInstance * +__new_instance(); + +void +__free_instance(struct __IonoInstance *instance); + +// result must be freed! +char * +__eval_js(const char *js, struct __IonoInstance *instance); + +void +__notify_instance(struct __IonoInstance *instance); + +void +__run_node(struct __IonoInstance *instance); + +void +__make_callback(const char *callback, struct __IonoInstance *instance); + +void +__put_module_code(const char *module_name, const char *module_code, struct IonoInstance *instance); + +#ifdef __cplusplus +} +#endif + +#endif /* node_wrapper_h */ |