You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+24-5Lines changed: 24 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,20 +52,39 @@ The high-level wrappers consist of a set of classes templated on class tag:
52
52
* `jni::Field<Tag, T>`, a wrapper for an instance field of the Java class associated with the tag, and providing `Get` and `Set` methods. The field type `T` is a jni.hpp primitive type or `Object<Tag>`.
53
53
* `jni::StaticField<Tag, T>`, a wrapper for a static field of the Java class associated with the tag, and providing `Get` and `Set` methods. The field type `T` is a jni.hpp primitive type or `Object<Tag>`.
54
54
55
-
Finally, the high-level wrappers provide the method `jni::NativeMethod` for binding native methods which use the high-level jni.hpp types. Given a `const char *` method name and a `Callable` object whose call signature uses high-level types, `jni::NativeMethod` returns a `jni::JNINativeMethod` struct that can be included in an array passed to `jni::RegisterNatives`. `jni::NativeMethod` takes care of:
55
+
## Method Registration
56
56
57
-
* Deducing and constructing the JNI type signature of the native method.
58
-
* Wrapping your code in a try/catch block that handles translating native exceptions to Java exceptions.
57
+
Registering native methods is a central part of JNI, and jni.hpp provides several features that make this task safer and more convenient. The jni.hpp wrapper method `jni::RegisterNatives` has the following signature:
59
58
60
-
The `Callable` object passed to `jni::NativeMethod` must be movable and uniquely typed -- lambdas are perfect.
In other words, rather than receiving a length and pointer to an array of `JNIMethod`s, it takes a variable number of variable types. This allows `jni::RegisterNatives` to type check the methods, ensuring that their type signatures are valid for JNI.
65
+
66
+
Use the helper function `jni::MakeNativeMethod` to construct method arguments for `jni::RegisterNatives`. `jni::MakeNativeMethod` wraps your method in a `try` / `catch` block that translates C++ exceptions to Java exceptions. It is overloaded on the following combinations of arguments:
67
+
68
+
* A `const char *` name, `const char *` signature, and lambda. The type of the first parameter of the lambda must be `jni::JNIEnv&`. The type of the second parameter must be either `jni::jclass*` (for a native static method) or `jni::jobject*` (for a native instance method). The result type must be a JNI primitive type or type convertable to `jni::jobject*`. (These requirements are type checked.)
69
+
* A `const char *` name, `const char *` signature, and function pointer. The function has the same parameter and return type requirements as the lambda. In order to guarantee a unique exception-handling wrapper for each unique function pointer, the function pointer must be provided as a _template parameter_ rather than method parameter:
The `decltype` is necessary because it is not possible to infer the types from a non-type template parameter. You may wish to use a macro to avoid repetition. See below for example code.
76
+
* A `const char *` name and lamba whose parameter and return types use high-level jni.hpp wrapper types. In this case, jni.hpp will compute the signature automatically.
77
+
* A `const char *` name and function pointer whose parameter and return types use high-level jni.hpp wrapper types. Again, jni.hpp will compute the signature automatically, and again, the function pointer must be provided as a template parameter rather than method parameter.
78
+
79
+
Finally, jni.hpp provides a mechanism for registering a "native peer": a long-lived native object corresponding to a Java object, usually created when the Java object is created and destroyed when the Java object's finalizer runs. Between creation and finalization, a pointer to the native peer is stored in a `long` field on the Java object. jni.hpp will take care of wrapping lambdas, function pointers, or member function pointers with code that automatically gets the value of this field, casts it to a pointer to the peer, and calls the member function (or passes a reference to the peer as an argument to the lambda or function pointer). See the example code for details.
61
80
62
81
## Example code
63
82
64
83
Example code for both the low-level and high-level wrappers is provided in [the `examples` subdirectory](https://github.com/mapbox/jni.hpp/tree/master/examples). This code shows the use of jni.hpp for:
65
84
66
85
* Binding native methods such that they can be called from Java.
67
86
* Calling back into Java methods from native code.
68
-
* Binding native methods for a "native peer": a long-lived native object corresponding to a Java object, usually created when the Java object is created and destroyed when the Java object's finalizer runs.
0 commit comments