diff --git a/package/android/CMakeLists.txt b/package/android/CMakeLists.txt index 185f19e0..d1519933 100644 --- a/package/android/CMakeLists.txt +++ b/package/android/CMakeLists.txt @@ -23,7 +23,6 @@ add_library( ../cpp/Surface.cpp ../cpp/SurfaceProvider.cpp ../cpp/Listener.cpp - ../cpp/jsi/JsiTypeTraits.cpp ../cpp/jsi/HybridObject.cpp ../cpp/jsi/Promise.cpp ../cpp/core/EngineWrapper.cpp diff --git a/package/cpp/FilamentProxy.cpp b/package/cpp/FilamentProxy.cpp index 3d5a0963..dcb8f57d 100644 --- a/package/cpp/FilamentProxy.cpp +++ b/package/cpp/FilamentProxy.cpp @@ -9,7 +9,6 @@ #include #include #include -#include "core/EngineWrapper.h" namespace margelo { @@ -47,14 +46,12 @@ jsi::Value FilamentProxy::get(jsi::Runtime& runtime, const jsi::PropNameID& prop if (name == "createEngine") { return jsi::Function::createFromHostFunction( runtime, jsi::PropNameID::forUtf8(runtime, "createEngine"), 1, - [this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { + [](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value { if (count != 1) { [[unlikely]]; throw jsi::JSError(runtime, "createEngine: Expected 1 argument(s), but received " + std::to_string(count) + "!"); } std::string backend = arguments[0].asString(runtime).utf8(runtime); - // TODO: Parse backend from string - EngineWrapper engine(filament::Engine::Backend::OPENGL); return jsi::Value(13); }); diff --git a/package/cpp/core/EngineWrapper.cpp b/package/cpp/core/EngineWrapper.cpp index 6220ee3e..19e63d46 100644 --- a/package/cpp/core/EngineWrapper.cpp +++ b/package/cpp/core/EngineWrapper.cpp @@ -21,7 +21,7 @@ EngineWrapper::~EngineWrapper() { } void EngineWrapper::loadHybridMethods() { - registerHybridMethod("test", &EngineWrapper::testHybrid, this); + registerHybridMethod("setSurfaceProvider", &EngineWrapper::setSurfaceProvider, this); } void EngineWrapper::setSurfaceProvider(std::shared_ptr surfaceProvider) { diff --git a/package/cpp/jsi/HybridObject.cpp b/package/cpp/jsi/HybridObject.cpp index 3f403a12..30139513 100644 --- a/package/cpp/jsi/HybridObject.cpp +++ b/package/cpp/jsi/HybridObject.cpp @@ -57,46 +57,6 @@ std::vector HybridObject::getPropertyNames(facebook::jsi::Runti return result; } -template -void HybridObject::registerHybridMethod(std::string name, - ReturnType(Derived::*method)(Args...), - Derived* derivedInstance) { - if (_methods.count(name) > 0) { - [[unlikely]]; - throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!"); - } - - // TODO(marc): Use std::shared_ptr instead of T* to keep a strong reference of derivedClass. - auto func = [this, derivedInstance, method](jsi::Runtime &runtime, - const jsi::Value &thisVal, - const jsi::Value *args, - size_t count) -> jsi::Value { - if constexpr (std::is_same_v) { - callMethod(derivedInstance, method, runtime, args, std::index_sequence_for{}); - return jsi::Value::undefined(); - } else { - ReturnType result = callMethod(derivedInstance, method, runtime, args, std::index_sequence_for{}); - return jsi::Value(result); - } - }; - _methods[name] = HybridFunction { - .function = func, - .parameterCount = sizeof...(Args) - }; -} - -template -ReturnType HybridObject::callMethod(ClassType* obj, - ReturnType(ClassType::*method)(Args...), - jsi::Runtime& runtime, - const jsi::Value* args, - std::index_sequence) { - return (obj->*method)(convertArgument(runtime, args[Is])...); -} -template -ArgType HybridObject::convertArgument(jsi::Runtime& runtime, const jsi::Value& arg) { - return JSIConverter::fromJSI(runtime, arg); -} } // margelo \ No newline at end of file diff --git a/package/cpp/jsi/HybridObject.h b/package/cpp/jsi/HybridObject.h index 72cc35db..82eddf3a 100644 --- a/package/cpp/jsi/HybridObject.h +++ b/package/cpp/jsi/HybridObject.h @@ -8,6 +8,7 @@ #include #include #include +#include "JSIConverter.h" namespace margelo { @@ -48,18 +49,46 @@ class HybridObject: public jsi::HostObject { std::unordered_map>> _functionCache; private: - template - ArgType convertArgument(jsi::Runtime& runtime, const jsi::Value& arg); - template - ReturnType callMethod(ClassType* obj, + jsi::Value callMethod(ClassType* obj, ReturnType(ClassType::*method)(Args...), jsi::Runtime& runtime, const jsi::Value* args, - std::index_sequence); + std::index_sequence) { + if constexpr (std::is_same_v) { + (obj->*method)(JSIConverter::fromJSI(runtime, args[Is])...); + return jsi::Value::undefined(); + } else { + ReturnType result = (obj->*method)(JSIConverter::fromJSI(runtime, args[Is])...); + return JSIConverter::toJSI(runtime, result); + } + } + protected: template - void registerHybridMethod(std::string name, ReturnType(Derived::*method)(Args...), Derived* derivedInstance); + void registerHybridMethod(std::string name, + ReturnType(Derived::*method)(Args...), + Derived* derivedInstance) { + if (_methods.count(name) > 0) { + throw std::runtime_error("Cannot add Hybrid Method \"" + name + "\" - a method with that name already exists!"); + } + + // TODO(marc): Use std::shared_ptr instead of T* to keep a strong reference of derivedClass. + auto func = [this, derivedInstance, method](jsi::Runtime &runtime, + const jsi::Value &thisVal, + const jsi::Value *args, + size_t count) -> jsi::Value { + return callMethod(derivedInstance, + method, + runtime, + args, + std::index_sequence_for{}); + }; + _methods[name] = HybridFunction { + .function = func, + .parameterCount = sizeof...(Args) + }; + } }; } // margelo diff --git a/package/cpp/jsi/JSIConverter.h b/package/cpp/jsi/JSIConverter.h index 727b3543..638e8270 100644 --- a/package/cpp/jsi/JSIConverter.h +++ b/package/cpp/jsi/JSIConverter.h @@ -20,6 +20,10 @@ struct JSIConverter { static_assert(always_false::value, "This type is not supported by the JSIConverter!"); return ArgType(); } + static jsi::Value toJSI(jsi::Runtime&, ArgType) { + static_assert(always_false::value, "This type is not supported by the JSIConverter!"); + return jsi::Value::undefined(); + } private: template @@ -31,6 +35,9 @@ struct JSIConverter { static int fromJSI(jsi::Runtime&, const jsi::Value& arg) { return static_cast(arg.asNumber()); } + static jsi::Value toJSI(jsi::Runtime&, int arg) { + return jsi::Value(arg); + } }; template<> @@ -38,6 +45,9 @@ struct JSIConverter { static double fromJSI(jsi::Runtime&, const jsi::Value& arg) { return arg.asNumber(); } + static jsi::Value toJSI(jsi::Runtime&, double arg) { + return jsi::Value(arg); + } }; template<> @@ -45,6 +55,9 @@ struct JSIConverter { static double fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { return arg.asBigInt(runtime).asInt64(runtime); } + static jsi::Value toJSI(jsi::Runtime& runtime, int64_t arg) { + return jsi::BigInt::fromInt64(runtime, arg); + } }; template<> @@ -52,6 +65,9 @@ struct JSIConverter { static double fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { return arg.asBigInt(runtime).asUint64(runtime); } + static jsi::Value toJSI(jsi::Runtime& runtime, uint64_t arg) { + return jsi::BigInt::fromUint64(runtime, arg); + } }; template<> @@ -59,6 +75,9 @@ struct JSIConverter { static bool fromJSI(jsi::Runtime&, const jsi::Value& arg) { return arg.asBool(); } + static jsi::Value toJSI(jsi::Runtime&, bool arg) { + return jsi::Value(arg); + } }; template<> @@ -66,6 +85,9 @@ struct JSIConverter { static std::string fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { return arg.asString(runtime).utf8(runtime); } + static jsi::Value toJSI(jsi::Runtime& runtime, const std::string& arg) { + return jsi::String::createFromUtf8(runtime, arg); + } }; template @@ -82,6 +104,14 @@ struct JSIConverter> { } return vector; } + static jsi::Value toJSI(jsi::Runtime& runtime, std::vector& vector) { + jsi::Array array(runtime, vector.size()); + for (size_t i = 0; i < vector.size(); i++) { + jsi::Value value = JSIConverter::toJSI(runtime, vector[i]); + array.setValueAtIndex(runtime, i, std::move(value)); + } + return array; + } }; template @@ -99,6 +129,15 @@ struct JSIConverter> { } return map; } + static jsi::Value toJSI(jsi::Runtime& runtime, std::unordered_map& map) { + jsi::Object object(runtime); + for (const auto& pair : map) { + jsi::Value value = JSIConverter::toJSI(runtime, pair.second); + jsi::String key = jsi::String::createFromUtf8(runtime, pair.first); + object.setProperty(runtime, key, std::move(value)); + } + return object; + } }; template @@ -112,6 +151,9 @@ struct JSIConverter::value>> static T fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) { return arg.asObject(runtime).asHostObject(runtime); } + static jsi::Value toJSI(jsi::Runtime& runtime, T& arg) { + return jsi::Object::createFromHostObject(runtime, arg); + } }; } // margelo