Git Product home page Git Product logo

fbjni's Introduction

fbjni

The Facebook JNI helpers library is designed to simplify usage of the Java Native Interface. The helpers were implemented to ease the integration of cross-platform mobile code on Android, but there are no Android specifics in the design. It can be used with any Java VM that supports JNI.

struct JMyClass : JavaClass<JMyClass> {
  static constexpr auto kJavaDescriptor = "Lcom/example/MyClass;";

  // Automatic inference of Java method descriptors.
  static std::string concatenate(
      alias_ref<JClass> clazz,
      // Automatic conversion to std::string.
      std::string prefix) {
    // Call methods easily.
    static const auto getSuffix = clazz->getStaticMethod<JString()>("getSuffix");
    // Manage JNI references automatically.
    local_ref<JString> jstr = getSuffix(clazz);
    // Automatic exception translation between Java and C++ (both ways).
    // No need to check exception state after each call.
    result += jstr->toStdString();
    // Automatic conversion from std::string.
    return result;
  }
};

Documentation

License

fbjni is Apache-2 licensed, as found in the LICENSE file.

fbjni's People

Contributors

alichtman avatar calvano-fb avatar cortinico avatar dreiss avatar erip avatar facebook-github-bot avatar gengjiawen avatar h-friederich avatar ispeters avatar javache avatar joshingtonstate avatar jwmcglynn avatar kind-serge avatar krystofwoldrich avatar lanza avatar mhorowitz avatar mrousavy avatar nickgerleman avatar nlutsenko avatar passy avatar simpleton avatar smeenai avatar swolchok avatar xcheng16 avatar zertosh avatar zpao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fbjni's Issues

Build issues since fbjni 0.5.0 release

Issue description

Since the release of fbjni 0.5.0 an hour ago, we have some issues building our React Native app.
This may not be an issue on fbjni site but rather bad semantic version ranging in react-native-vision-camera

FAILURE: Build failed with an exception.
* Where:
Build file '/builds/X/node_modules/react-native-vision-camera/android/build.gradle' line: 570
Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.
* What went wrong:
Execution failed for task ':react-native-vision-camera:extractAARHeaders'.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
> Could not resolve all files for configuration ':react-native-vision-camera:extractHeaders'.
   > Could not find fbjni-0.5.0-headers.jar (com.facebook.fbjni:fbjni:0.5.0).
See https://docs.gradle.org/7.2/userguide/command_line_interface.html#sec:command_line_warnings
     Searched in the following locations:
         https://repo.maven.apache.org/maven2/com/facebook/fbjni/fbjni/0.5.0/fbjni-0.5.0-headers.jar

I see the fbjni-X-headers.jar have been removed in 0.5.0, it was present in 0.4.0.

System Info

Please include your compiler version and target platform

  • Android Build
  • Linux Computer
  • react-native-vision-camera 2.15.2
  • react-native: 0.69.4

fbjni-0.5.0-headers.jar responds in 404

Issue description

When deploying our React Native 0.70.6 app to Android through Fastlane we're now getting failed builds with the following error;

* Where:
Build file 'node_modules/react-native-mmkv/android/build.gradle' line: 322

* What went wrong:
Execution failed for task ':react-native-mmkv:extractAARHeaders'.
> Could not resolve all files for configuration ':react-native-mmkv:extractHeaders'.
   > Could not find fbjni-0.5.0-headers.jar (com.facebook.fbjni:fbjni:0.5.0).
     Searched in the following locations:
         https://repo.maven.apache.org/maven2/com/facebook/fbjni/fbjni/0.5.0/fbjni-0.5.0-headers.jar

Code example

When looking through https://repo.maven.apache.org/maven2/com/facebook/fbjni/fbjni we see that the headers file is missing only for version 0.5.0.

https://repo.maven.apache.org/maven2/com/facebook/fbjni/fbjni/0.5.0/fbjni-0.5.0-headers.jar responds in 404.

System Info

Deployment from Linux CI env. using Fastlane.

Is this repo still being maintained?

I've been waiting for some engagement on some PRs to fix the build for fbjni and to add Windows support, but haven't had much success. Given that and that the last update was in July, I wanted to inquire about the status of this project. I understand that this is an incubating project, but because PyTorch is relying on this repo I want to ensure that this is neither a dead project nor a project that can only get attention from Facebook employees.

Can it call the method in torch ?

I'm very glad to see such a good project!!!
We call a lot of the pytorch model in the java server by rpc api
Can I use this to call pytorch's C + + interface directly ?
How about the performance at high concurrency?
hope some exampels

Could not find a package configuration file provided by "fbjni"

Issue description

Created a brand new ndk project, CMake reported an error:

Could not find a package configuration file provided by "fbjni" with any of
  the following names:

    fbjniConfig.cmake
    fbjni-config.cmake

  Add the installation prefix of "fbjni" to CMAKE_PREFIX_PATH or set
  "fbjni_DIR" to a directory containing one of the above files.  If "fbjni"
  provides a separate development package or SDK, be sure it has been
  installed.

Code example

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.10.2)

# Declares and names the project.

project("fbjnitest")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )
set(build_DIR ${CMAKE_SOURCE_DIR}/build)
find_package(fbjni REQUIRED CONFIG)

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib}
        fbjni::fbjni)

System Info

CMake version: 3.10.2
Gradle Plugin version: 4.1.2
Gradle version: 6.5

Gradle project build fails on libc++_shared.so conflicts.

Issue description

Usage of fbjni in conjuction with other libraries can cause conflicts of libc++_shared.so

image

Conflicts can be resolved using

packagingOptions {
        pickFirst "lib/armeabi-v7a/libc++_shared.so"
        pickFirst "lib/arm64-v8a/libc++_shared.so"
        pickFirst "lib/x86/libc++_shared.so"
        pickFirst "lib/x86_64/libc++_shared.so"
    }

but such trick causes crash in runtime, because any dependency can get incompatible version of c++ shared library.

java.lang.UnsatisfiedLinkError: Bad JNI version returned from JNI_OnLoad in "/data/app/~~ZbHqrsKgKEnQcU1uwQ4pnw==/foo.bar.baz-macXtsVqrzK5TJV017tYQw==/HTTP://WEBADDRESS.ELIDED!/lib/arm64-v8a/HTTP://WEBADDRESS.ELIDED": 0
	at java.lang.Runtime.loadLibrary0(Runtime.java:1087)
	at java.lang.Runtime.loadLibrary0(Runtime.java:1008)
	at java.lang.System.loadLibrary(System.java:1664)

libjni should be compiled using static libc++ and published in maven.

System Info

Linux

Calling from C++ into Java with local_ref may crash

Issue description

If a C++ call is made to a Java method whose reference is obtained by getMethod with local_ref arguments types, and that call throws an exception, it causes the process to crash. fbjni does not prevent specifying Java methods descriptors arguments in terms of local_ref.

This will only happen in debug builds because the crash is caused by a call to verifyReference in local_ref dtor, that is made inside an assert statement. verifyReference calls GetObjectRefType which is not allowed when there's a pending Java exception.

For release builds there is no issue because the actual JNI call to destroy a reference (DeleteLocalRef) is safe to call when there is a pending Java exception.

Code example

class JFoo : public facebook::jni::JavaClass<JFoo> {
  public:
  static constexpr auto kJavaDescriptor = "Lcom/example/Foo;";

  static void bar(facebook::jni::local_ref<JObject> jObj) {
    static auto method = javaClassStatic()->
                    getMethod<void(facebook::jni::local_ref<JObject>)>(
                    "bar");

    method(javaClassStatic(), jObj);
  }
};
package com.example
object Foo {
  @JvmStatic
  void bar(obj: Any) {
    throw Exception()
  }
}

Now a call such as this will crash:

JFoo::bar(facebook::jni::make_jstring(""));

Windows build fails with Android NDK r21d

Issue description

Compilation fails (with >100 errors) on Windows with Android NDK.

Provide a short description.

Based on comments in the CMakeLists.txt, Windows builds could potentially be supported with Android NDK JNI rather than default JDK JNI bundles due to sizeof issues. This ticket tracks that.

Code example

Patch for CMakeLists.txt:

diff --git CMakeLists.txt CMakeLists.txt
index 10ec200..0f8a717 100644
--- CMakeLists.txt
+++ CMakeLists.txt
@@ -44,24 +44,29 @@ target_include_directories(fbjni PUBLIC
 )

 if (NOT ANDROID_ABI)
-  if (NOT JAVA_HOME)
-    message(FATAL_ERROR
-      "fbjni requires JAVA_HOME to be defined for non-Android builds.")
-  endif()
-  target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include)
-  if (CMAKE_SYSTEM_NAME STREQUAL Linux)
-    target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include/linux)
-  endif()
-  if (CMAKE_SYSTEM_NAME STREQUAL Darwin)
-    target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include/darwin)
-  endif()
   # win32/jni_md.h typedefs jint as long, because apparently
   # long is 32 bits on Windows.  This breaks a lot of stuff.
   # It could probably be fixed, but for now just require
   # building with Android's jni.h on Windows, which doesn't do this.
-  # if (CMAKE_SYSTEM_NAME STREQUAL Windows)
-  #   target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include/win32)
-  # endif()
+  if (CMAKE_SYSTEM_NAME STREQUAL Windows)
+    if (NOT NDK_HOME)
+      message(FATAL_ERROR
+        "fbjni requires NDK_HOME to be defined for Windows builds.")
+    endif()
+     target_include_directories(fbjni PUBLIC ${NDK_HOME}/sysroot/usr/include)
+  else()
+    if (NOT JAVA_HOME)
+      message(FATAL_ERROR
+        "fbjni requires JAVA_HOME to be defined for non-Android builds.")
+    endif()
+    target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include)
+    if (CMAKE_SYSTEM_NAME STREQUAL Linux)
+      target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include/linux)
+    endif()
+    if (CMAKE_SYSTEM_NAME STREQUAL Darwin)
+      target_include_directories(fbjni PUBLIC ${JAVA_HOME}/include/darwin)
+    endif()
+  endif()

   if(NOT FBJNI_SKIP_TESTS)
     enable_testing()

Build process:

git clone https://github.com/facebookincubator/fbjni
mkdir -p fbjni/build 
cd fbjni/build
cmake .. -DNDK_HOME="%NDK_HOME%"
cmake --build . --config Release -- -j4

I'm building on Windows with Android NDK r21d and MSVC 19.27.29111 for x64.

AAR packaged libc++_shared.so?

Issue description

The libc++_shared.so shipped with fbjni.aar conflicts with our app's.
According to android official doc, they recommended libraries to ship native code as a single so file.
Want to know why we don't static link it to single fbjni.so?
And is there any suggested way to resolve native conflicts like this?

thanks.

System Info

Android

Upload version 0.0.3 to Maven Central Repository

Our React Native project requires com.facebook.fbjni:fbjni-java-only:0.0.3 which is currently only available on jcenter. Since jcenter is to be closed, it is crucial for us to be able to download com.facebook.fbjni:fbjni-java-only:0.0.3 from Maven Central Repository. Now it only contains versions 0.0.4 and newer. Meanwhile, 0.0.3 is a dependency required by the latest React Native release (0.64.2)

New release? 0.2.3

Hey! I'm trying to use ArrayList<T> and HashMap<K, V> in JNI, but 0.2.2 (current latest release) does not contain those bindings. A week ago a commit landed on master (by @dreiss: f730250) that implemented both bindings, can you publish a release for that?

Thanks!

JVM doesn't terminate when using Hybrids

Issue description

In any program that uses HybridData, the JVM will not terminate when main returns. Calling System.exit still terminates cleanly. This appears to be because the Hybrid Destructor thread is not marked as a daemon thread. Calling sThread.setDaemon(true); resolves the issue, but I'm not sure if it can cause issues on Android.

Code example

Apply this patch:

diff --git a/host.gradle b/host.gradle
index 39f2d55..d88b96a 100644
--- a/host.gradle
+++ b/host.gradle
@@ -15,6 +15,8 @@
  */
 
 plugins {
+    id 'java'
+    id 'application'
     id 'java-library'
     id 'com.github.dcendents.android-maven' version '2.1'
     id 'com.jfrog.bintray' version '1.8.4'
@@ -47,3 +49,7 @@ POM_PACKAGING = 'jar'
 POM_ARTIFACT_ID = 'fbjni-java-only'
 
 apply from: rootProject.file('gradle/release.gradle')
+
+application {
+    mainClassName = 'com.facebook.jni.HybridRepro'
+}
diff --git a/java/com/facebook/jni/HybridRepro.java b/java/com/facebook/jni/HybridRepro.java
new file mode 100644
index 0000000..9b37056
--- /dev/null
+++ b/java/com/facebook/jni/HybridRepro.java
@@ -0,0 +1,14 @@
+package com.facebook.jni;
+
+import com.facebook.soloader.nativeloader.NativeLoader;
+import com.facebook.soloader.nativeloader.SystemDelegate;
+
+public class HybridRepro {
+  public static void main(String[] args) {
+    NativeLoader.init(new SystemDelegate());
+    new HybridData();
+    if (args.length > 0 && args[0].equals("exit")) {
+      System.exit(0);
+    }
+  }
+}

Running as ./gradlew -b host.gradle run --args nope causes the app to run forever.
Running as ./gradlew -b host.gradle run --args exit causes the app to terminate quickly.

System Info

Linux.

Is there any example for creating a Hybrid class?

As I understand about the Hybrid (correct me if I'm wrong), it is a glue to bind an C++ object to a Java object, and is useful to handle C++ lifetime.

But I didn't find any docs about how to use them, so is there any examples?

Passing a Java interface to C++

Issue description

Hi! I'm trying to pass an instance of a Java interface to C++.

The interface I'm trying to use is the ImageProxy interface from AndroidX/CameraX, my C++ declaration for the binding/interface looks like this:

struct JImageProxy : public facebook::jni::JavaClass<JImageProxy> {
  static constexpr auto kJavaDescriptor = "Landroidx.camera.core/ImageProxy;";
};

and my C++ method looks like this:

void callback(jni::alias_ref<JImageProxy::javaobject> image);

and the Java (Kotlin) native func decl looks like this:

  private external fun callback(image: ImageProxy)

but my app crashes with the following exception:

2021-06-22 14:32:17.108 31506-31506/? E/.camera.exampl: Failed to register native method com.mrousavy.camera.CameraView.frameProcessorCallback(Landroidx.camera.core/ImageProxy;)V in /data/app/com.mrousavy.camera.example-22C3je6eP10VxqF5O-UTMw==/base.apk!classes4.dex
2021-06-22 14:32:17.109 31506-31506/? E/log: error java.lang.NoSuchMethodError: no static or non-static method "Lcom/mrousavy/camera/CameraView;.frameProcessorCallback(Landroidx.camera.core/ImageProxy;)V"

Does anyone know why this keeps happening? Did I declare something wrong? Does fbjni not support Java interfaces?

System Info

MacOS Big Sur 11.4, latest fbjni

Publish a more recent build of the fbjni shared object

Issue description

Hey,
First, thanks a lot for sharing your well written library in an external repo!

Prior to this repo, we've been using some version of it which was embedded in React Native, and had to
learn its usage from React's code, and now you've given us a good load of examples of best practices.

Anyways, my only question to you is whether you're planning to publish a more recent build of libfbjni.so to bintray's Jcenter, currently we have a frankstein-ish build that uses 0.0.3 java part from Jcenter whereas we build libfbjni.so locally.

If I can help in some manner to make that happen, let me know, I'll glady contribute.
Another side note, it will be helpful if tags were incorporated into the repo denoting each release.

Keep up the awesome work!

Max, Autodesk.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.