Skip to content

Commit

Permalink
fix: Fix templates
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Feb 21, 2024
1 parent 5ace254 commit a739bd0
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 52 deletions.
1 change: 0 additions & 1 deletion package/android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions package/cpp/FilamentProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <memory>
#include <string>
#include <vector>
#include "core/EngineWrapper.h"

namespace margelo {

Expand Down Expand Up @@ -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);
});
Expand Down
2 changes: 1 addition & 1 deletion package/cpp/core/EngineWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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> surfaceProvider) {
Expand Down
40 changes: 0 additions & 40 deletions package/cpp/jsi/HybridObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,46 +57,6 @@ std::vector<jsi::PropNameID> HybridObject::getPropertyNames(facebook::jsi::Runti
return result;
}

template<typename Derived, typename ReturnType, typename... Args>
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<T> 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<ReturnType, void>) {
callMethod(derivedInstance, method, runtime, args, std::index_sequence_for<Args...>{});
return jsi::Value::undefined();
} else {
ReturnType result = callMethod(derivedInstance, method, runtime, args, std::index_sequence_for<Args...>{});
return jsi::Value(result);
}
};
_methods[name] = HybridFunction {
.function = func,
.parameterCount = sizeof...(Args)
};
}

template<typename ClassType, typename ReturnType, typename... Args, size_t... Is>
ReturnType HybridObject::callMethod(ClassType* obj,
ReturnType(ClassType::*method)(Args...),
jsi::Runtime& runtime,
const jsi::Value* args,
std::index_sequence<Is...>) {
return (obj->*method)(convertArgument<Args>(runtime, args[Is])...);
}

template<typename ArgType>
ArgType HybridObject::convertArgument(jsi::Runtime& runtime, const jsi::Value& arg) {
return JSIConverter<ArgType>::fromJSI(runtime, arg);
}

} // margelo
41 changes: 35 additions & 6 deletions package/cpp/jsi/HybridObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>
#include <unordered_map>
#include <jsi/jsi.h>
#include "JSIConverter.h"

namespace margelo {

Expand Down Expand Up @@ -48,18 +49,46 @@ class HybridObject: public jsi::HostObject {
std::unordered_map<jsi::Runtime*, std::unordered_map<std::string, std::shared_ptr<jsi::Function>>> _functionCache;

private:
template<typename ArgType>
ArgType convertArgument(jsi::Runtime& runtime, const jsi::Value& arg);

template<typename ClassType, typename ReturnType, typename... Args, size_t... Is>
ReturnType callMethod(ClassType* obj,
jsi::Value callMethod(ClassType* obj,
ReturnType(ClassType::*method)(Args...),
jsi::Runtime& runtime,
const jsi::Value* args,
std::index_sequence<Is...>);
std::index_sequence<Is...>) {
if constexpr (std::is_same_v<ReturnType, void>) {
(obj->*method)(JSIConverter<Args>::fromJSI(runtime, args[Is])...);
return jsi::Value::undefined();
} else {
ReturnType result = (obj->*method)(JSIConverter<Args>::fromJSI(runtime, args[Is])...);
return JSIConverter<ReturnType>::toJSI(runtime, result);
}
}

protected:
template<typename Derived, typename ReturnType, typename... Args>
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<T> 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<Args...>{});
};
_methods[name] = HybridFunction {
.function = func,
.parameterCount = sizeof...(Args)
};
}
};

} // margelo
Expand Down
42 changes: 42 additions & 0 deletions package/cpp/jsi/JSIConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ struct JSIConverter {
static_assert(always_false<ArgType>::value, "This type is not supported by the JSIConverter!");
return ArgType();
}
static jsi::Value toJSI(jsi::Runtime&, ArgType) {
static_assert(always_false<ArgType>::value, "This type is not supported by the JSIConverter!");
return jsi::Value::undefined();
}

private:
template<typename>
Expand All @@ -31,41 +35,59 @@ struct JSIConverter<int> {
static int fromJSI(jsi::Runtime&, const jsi::Value& arg) {
return static_cast<int>(arg.asNumber());
}
static jsi::Value toJSI(jsi::Runtime&, int arg) {
return jsi::Value(arg);
}
};

template<>
struct JSIConverter<double> {
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<>
struct JSIConverter<int64_t> {
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<>
struct JSIConverter<uint64_t> {
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<>
struct JSIConverter<bool> {
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<>
struct JSIConverter<std::string> {
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<typename ElementType>
Expand All @@ -82,6 +104,14 @@ struct JSIConverter<std::vector<ElementType>> {
}
return vector;
}
static jsi::Value toJSI(jsi::Runtime& runtime, std::vector<ElementType>& vector) {
jsi::Array array(runtime, vector.size());
for (size_t i = 0; i < vector.size(); i++) {
jsi::Value value = JSIConverter<ElementType>::toJSI(runtime, vector[i]);
array.setValueAtIndex(runtime, i, std::move(value));
}
return array;
}
};

template<typename ValueType>
Expand All @@ -99,6 +129,15 @@ struct JSIConverter<std::unordered_map<std::string, ValueType>> {
}
return map;
}
static jsi::Value toJSI(jsi::Runtime& runtime, std::unordered_map<std::string, ValueType>& map) {
jsi::Object object(runtime);
for (const auto& pair : map) {
jsi::Value value = JSIConverter<ValueType>::toJSI(runtime, pair.second);
jsi::String key = jsi::String::createFromUtf8(runtime, pair.first);
object.setProperty(runtime, key, std::move(value));
}
return object;
}
};

template<typename T>
Expand All @@ -112,6 +151,9 @@ struct JSIConverter<T, std::enable_if_t<is_shared_ptr_to_host_object<T>::value>>
static T fromJSI(jsi::Runtime& runtime, const jsi::Value& arg) {
return arg.asObject(runtime).asHostObject<typename T::element_type>(runtime);
}
static jsi::Value toJSI(jsi::Runtime& runtime, T& arg) {
return jsi::Object::createFromHostObject(runtime, arg);
}
};

} // margelo
Expand Down

0 comments on commit a739bd0

Please sign in to comment.