diff --git a/crates/ubrn_cli/templates/jsi/android/cpp-adapter.cpp b/crates/ubrn_cli/templates/jsi/android/cpp-adapter.cpp index d8d1c1a1c1269ecee9467fd0ef809dcb1e375923..a031428d1eaecec2df94e7148e9d45d15642158d 100644 --- a/crates/ubrn_cli/templates/jsi/android/cpp-adapter.cpp +++ b/crates/ubrn_cli/templates/jsi/android/cpp-adapter.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "{{ self.config.project.cpp_filename() }}.h" {%- let package_name = self.config.project.android.package_name().replace(".", "_") %} {%- let name = self.config.project.module_cpp() %} @@ -29,35 +30,27 @@ JNIEXPORT jboolean JNICALL jlong rtPtr, jobject callInvokerHolderJavaObj ) { - // https://github.com/realm/realm-js/blob/main/packages/realm/binding/android/src/main/cpp/io_realm_react_RealmReactModule.cpp#L122-L145 - // React Native uses the fbjni library for handling JNI, which has the concept of "hybrid objects", - // which are Java objects containing a pointer to a C++ object. The CallInvokerHolder, which has the - // invokeAsync method we want access to, is one such hybrid object. - // Rather than reworking our code to use fbjni throughout, this code unpacks the C++ object from the Java - // object `callInvokerHolderJavaObj` manually, based on reverse engineering the fbjni code. - - // 1. Get the Java object referred to by the mHybridData field of the Java holder object - auto callInvokerHolderClass = env->GetObjectClass(callInvokerHolderJavaObj); - auto hybridDataField = env->GetFieldID(callInvokerHolderClass, "mHybridData", "Lcom/facebook/jni/HybridData;"); - auto hybridDataObj = env->GetObjectField(callInvokerHolderJavaObj, hybridDataField); - - // 2. Get the destructor Java object referred to by the mDestructor field from the myHybridData Java object - auto hybridDataClass = env->FindClass("com/facebook/jni/HybridData"); - auto destructorField = - env->GetFieldID(hybridDataClass, "mDestructor", "Lcom/facebook/jni/HybridData$Destructor;"); - auto destructorObj = env->GetObjectField(hybridDataObj, destructorField); - - // 3. Get the mNativePointer field from the mDestructor Java object - auto destructorClass = env->FindClass("com/facebook/jni/HybridData$Destructor"); - auto nativePointerField = env->GetFieldID(destructorClass, "mNativePointer", "J"); - auto nativePointerValue = env->GetLongField(destructorObj, nativePointerField); - - // 4. Cast the mNativePointer back to its C++ type - auto nativePointer = reinterpret_cast(nativePointerValue); - auto jsCallInvoker = nativePointer->getCallInvoker(); - - auto runtime = reinterpret_cast(rtPtr); - return {{ ns }}::installRustCrate(*runtime, jsCallInvoker); + try { + if (callInvokerHolderJavaObj == nullptr) { + return false; + } + + auto alias = facebook::jni::alias_ref(callInvokerHolderJavaObj); + auto holder = facebook::jni::static_ref_cast(alias); + if (!holder) { + return false; + } + + auto jsCallInvoker = holder->cthis()->getCallInvoker(); + if (!jsCallInvoker) { + return false; + } + + auto runtime = reinterpret_cast(rtPtr); + return {{ ns }}::installRustCrate(*runtime, jsCallInvoker); + } catch (...) { + return false; + } } extern "C"