Skip to content

Commit

Permalink
Create C++ base
Browse files Browse the repository at this point in the history
  • Loading branch information
mrousavy committed Feb 20, 2024
1 parent e14a9cf commit 07cf460
Show file tree
Hide file tree
Showing 14 changed files with 319 additions and 0 deletions.
23 changes: 23 additions & 0 deletions package/android/src/main/cpp/AndroidFilamentProxy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#include "AndroidFilamentProxy.h"

namespace margelo {

using namespace facebook;

explicit AndroidFilamentProxy::AndroidFilamentProxy(jni::alias_ref<JFilamentProxy> filamentProxy):
_filamentProxy(jni::make_global(filamentProxy)) { }

AndroidFilamentProxy::~AndroidFilamentProxy() {
// Hermes GC might destroy HostObjects on an arbitrary Thread which might not be
// connected to the JNI environment. To make sure fbjni can properly destroy
// the Java method, we connect to a JNI environment first.
jni::ThreadScope::WithClassLoader([&] { _filamentProxy.reset(); });
}

int AndroidFilamentProxy::loadModel(const std::string& path) {
return _proxy->loadModel(path);
}
32 changes: 32 additions & 0 deletions package/android/src/main/cpp/AndroidFilamentProxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#pragma once

#include "FilamentProxy.h"
#include "java-bindings/JFilamentProxy.h"
#include <fbjni/fbjni.h>
#include <jni.h>

namespace margelo {

using namespace facebook;

/**
* Implementation for the abstract class FilamentProxy, which uses the JNI Hybrid Class "JFilamentProxy" underneath.
*/
class AndroidFilamentProxy : public FilamentProxy {
public:
explicit AndroidFilamentProxy(jni::alias_ref<JFilamentProxy> filamentProxy);
~AndroidFilamentProxy();

private:
// TODO(hanno): implement
int loadModel(const std::string& path);

private:
jni::global_ref<JFilamentProxy> _proxy;
};

} // namespace margelo
8 changes: 8 additions & 0 deletions package/android/src/main/cpp/Filament.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#include <fbjni/fbjni.h>
#include <jni.h>

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
return facebook::jni::initialize(vm, [] {
margelo::FilamentInstaller::registerNatives();
});
}
Empty file.
19 changes: 19 additions & 0 deletions package/android/src/main/cpp/FilamentInstaller.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#include <fbjni/fbjni.h>
#include <jni.h>

namespace margelo {

using namespace facebook;

class FilamentInstaller : public jni::JavaClass<FilamentInstaller> {
public:
static auto constexpr kJavaDescriptor = "Lcom/margelo/filament/FilamentInstaller;";
static void registerNatives();
static void install(jni::alias_ref<jni::JClass> clazz, jni::alias_ref<JVisionCameraProxy::javaobject> proxy);
};

}; // namespace margelo
44 changes: 44 additions & 0 deletions package/android/src/main/cpp/java-bindings/JFilamentProxy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#include "JFilamentProxy.h"
#include <fbjni/fbjni.h>

namespace margelo {

using namespace facebook;


JFilamentProxy::JFilamentProxy(const jni::alias_ref<JFilamentProxy::jhybridobject>& javaThis,
jsi::Runtime* runtime,
const std::shared_ptr<facebook::react::CallInvoker>& callInvoker):
_javaPart(make_global(javaThis)), _runtime(runtime), _callInvoker(callInvoker) { }


JFilamentProxy::~JFilamentProxy() {
// TODO(hanno): Cleanup?
}

int JFilamentProxy::loadModel(const std::string& path) {
static const auto method = javaClassLocal()->getMethod<jint(jstring)>("loadModel");
return method(_javaPart, make_jstring(path));
}

void JFilamentProxy::registerNatives() {
registerHybrid({makeNativeMethod("initHybrid", JFilamentProxy::initHybrid)});
}

jni::local_ref<JFilamentProxy::jhybriddata> JFilamentProxy::initHybrid(alias_ref<jhybridobject> jThis,
jlong jsRuntimePointer,
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject> jsCallInvokerHolder) {
__android_log_write(ANDROID_LOG_INFO, TAG, "Initializing JFilamentProxy...");

// cast from JNI hybrid objects to C++ instances
auto jsRuntime = reinterpret_cast<jsi::Runtime*>(jsRuntimePointer);
auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker();

return makeCxxInstance(jThis, jsRuntime, jsCallInvoker);
}

} // namespace margelo
46 changes: 46 additions & 0 deletions package/android/src/main/cpp/java-bindings/JFilamentProxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#pragma once

#include <fbjni/fbjni.h>
#include <jsi/jsi.h>
#include <jni.h>
#include <ReactCommon/CallInvokerHolder.h>

namespace margelo {

using namespace facebook;

/**
* Bindings to the Java class "FilamentProxy.java".
*/
class JFilamentProxy : public jni::HybridClass<JFilamentProxy> {
public:
~JFilamentProxy();
static void registerNatives();

// TODO(hanno): implement
int loadModel(const std::string& path);

private:
friend HybridBase;
jni::global_ref<JFilamentProxy::javaobject> _javaPart;
jsi::Runtime* _runtime;
std::shared_ptr<facebook::react::CallInvoker> _callInvoker;

private:
static auto constexpr TAG = "FilamentProxy";
static auto constexpr kJavaDescriptor = "Lcom/margelo/filament/FilamentProxy;";

private:
explicit JFilamentProxy(const jni::alias_ref<JFilamentProxy::jhybridobject>& javaThis,
jsi::Runtime* jsRuntime,
const std::shared_ptr<facebook::react::CallInvoker>& jsCallInvoker);
static jni::local_ref<jhybriddata> initHybrid(jni::alias_ref<jhybridobject> javaThis,
jlong jsRuntimePointer,
jni::alias_ref<facebook::react::CallInvokerHolder::javaobject> jsCallInvokerHolder);
};

} // namespace vision
42 changes: 42 additions & 0 deletions package/cpp/FilamentProxy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#include "FilamentProxy.h"
#include <jsi/jsi.h>

#include <memory>
#include <string>
#include <vector>
#include "jsi/Promise.h"

namespace margelo {

using namespace facebook;

std::vector<jsi::PropNameID> FilamentProxy::getPropertyNames(jsi::Runtime& runtime) {
std::vector<jsi::PropNameID> result;
// TODO(hanno): add more methods here?
result.push_back(jsi::PropNameID::forUtf8(runtime, std::string("loadModel")));
return result;
}

jsi::Value FilamentProxy::get(jsi::Runtime& runtime, const jsi::PropNameID& propName) {
auto name = propName.utf8(runtime);

if (name == "loadModel") {
return jsi::Function::createFromHostFunction(
runtime, jsi::PropNameID::forUtf8(runtime, "loadModel"), 1,
[this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments, size_t count) -> jsi::Value {
// TODO(hanno): If this should be sync, we don't need a Promise.
return Promise::createPromise(runtime, [this](std::shared_ptr<Promise> promise) -> {
// TODO(hanno): If this should be async, we need to run this on a separate Thread (ask me for a Thread Pool implementation),
// then dispatch back to the JS Thread for safely resolving the Promise using the CallInvoker.
auto model = this->loadModel();
promise->resolve(model);
});
});
}

return jsi::Value::undefined();
}
29 changes: 29 additions & 0 deletions package/cpp/FilamentProxy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// Created by Marc Rousavy on 20.02.24.
//

#pragma once

#include <jsi/jsi.h>

#include <string>
#include <vector>

namespace margelo {

using namespace facebook;

class FilamentProxy : public jsi::HostObject {
public:
virtual ~FilamentProxy();

private:
// TODO(hanno): implement
virtual int loadModel(const std::string& path);

public:
std::vector<jsi::PropNameID> getPropertyNames(jsi::Runtime& runtime) override;
jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override;
};

} // namespace vision
43 changes: 43 additions & 0 deletions package/cpp/jsi/Promise.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include "Promise.h"
#include <future>
#include <jsi/jsi.h>
#include <utility>
#include <vector>

namespace margelo {

using namespace facebook;

Promise::Promise(jsi::Runtime& runtime, jsi::Value resolver, jsi::Value rejecter)
: runtime(runtime), _resolver(std::move(resolver)), _rejecter(std::move(rejecter)) {}

jsi::Value Promise::createPromise(jsi::Runtime& runtime,
std::function<void(std::shared_ptr<Promise> promise)> run) {
// Get Promise ctor from global
auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");

auto promiseCallback = jsi::Function::createFromHostFunction(
runtime, jsi::PropNameID::forUtf8(runtime, "PromiseCallback"), 2,
[=](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
size_t count) -> jsi::Value {
// Call function
auto promise = std::make_shared<Promise>(runtime, arguments[0].asObject(runtime),
arguments[1].asObject(runtime));
run(promise);

return jsi::Value::undefined();
});

return promiseCtor.callAsConstructor(runtime, promiseCallback);
}

void Promise::resolve(jsi::Value&& result) {
_resolver.asObject(runtime).asFunction(runtime).call(runtime, std::move(result));
}

void Promise::reject(std::string message) {
jsi::JSError error(runtime, message);
_rejecter.asObject(runtime).asFunction(runtime).call(runtime, error.value());
}

} // namespace margelo
33 changes: 33 additions & 0 deletions package/cpp/jsi/Promise.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <jsi/jsi.h>
#include <utility>
#include <vector>

namespace margelo {

using namespace facebook;

class Promise {
public:
Promise(jsi::Runtime& runtime, jsi::Value resolver, jsi::Value rejecter);

void resolve(jsi::Value&& result);
void reject(std::string error);

public:
jsi::Runtime& runtime;

private:
jsi::Value _resolver;
jsi::Value _rejecter;

public:
/**
Create a new Promise and runs the given `run` function.
*/
static jsi::Value createPromise(jsi::Runtime& runtime,
std::function<void(std::shared_ptr<Promise> promise)> run);
};

} // namespace margelo

0 comments on commit 07cf460

Please sign in to comment.