JNI Bindings #6

Open
opened 2022-10-14 18:08:58 +00:00 by Lonami · 1 comment

Currently the JNI bindings bridging the Kotlin-Rust world are written by hand. This is both tedious and error-prone. There are several projects that could help:

Another alternative is to keep the surface extremely small, with essentially two functions, write and read, and in a similar style to traditional RPC, serializing and deserializing messages in some protocol.

One such option would be Cap'n Proto, but there are other options.

Currently the JNI bindings bridging the Kotlin-Rust world are written by hand. This is both tedious and error-prone. There are several projects that could help: * [mozilla/uniffi-rs](https://github.com/mozilla/uniffi-rs). This seems like a solid bet. * [rust-diplomat/diplomat](https://github.com/rust-diplomat/diplomat/). Unfortunately [Java support is not quite ready](https://github.com/rust-diplomat/diplomat/issues/144). * [giovanniberti/robusta](https://github.com/giovanniberti/robusta). It does not seem to offer many features but it may be enough. * [Dushistov/flapigen-rs](https://github.com/Dushistov/flapigen-rs). It does not seem very polished at first glance. * Several others listed in [areweextendingyet](https://areweextendingyet.github.io/). Another alternative is to keep the surface extremely small, with essentially two functions, `write` and `read`, and in a similar style to traditional RPC, serializing and deserializing messages in some protocol. One such option would be [Cap'n Proto](https://capnproto.org/), but there are other options.
Poster
Owner

If we go the manual route, the Guide to JNI (Java Native Interface) has an example on how to create Java objects from C++, which could prove useful:

public native UserData createUser(String name, double balance);
    
public native String printUserData(UserData user);
JNIEXPORT jobject JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_createUser
  (JNIEnv *env, jobject thisObject, jstring name, jdouble balance) {
  
    // Create the object of the class UserData
    jclass userDataClass = env->FindClass("com/baeldung/jni/UserData");
    jobject newUserData = env->AllocObject(userDataClass);
  
    // Get the UserData fields to be set
    jfieldID nameField = env->GetFieldID(userDataClass , "name", "Ljava/lang/String;");
    jfieldID balanceField = env->GetFieldID(userDataClass , "balance", "D");
  
    env->SetObjectField(newUserData, nameField, name);
    env->SetDoubleField(newUserData, balanceField, balance);
    
    return newUserData;
}

JNIEXPORT jstring JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_printUserData
  (JNIEnv *env, jobject thisObject, jobject userData) {
    
    // Find the id of the Java method to be called
    jclass userDataClass=env->GetObjectClass(userData);
    jmethodID methodId=env->GetMethodID(userDataClass, "getUserInfo", "()Ljava/lang/String;");

    jstring result = (jstring)env->CallObjectMethod(userData, methodId);
    return result;
}

The jni Rust dependency may need to be updated to account for other features.

If we go the manual route, the [Guide to JNI (Java Native Interface)](https://www.baeldung.com/jni) has an example on how to create Java objects from C++, which could prove useful: ```java public native UserData createUser(String name, double balance); public native String printUserData(UserData user); ``` ```cpp JNIEXPORT jobject JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_createUser (JNIEnv *env, jobject thisObject, jstring name, jdouble balance) { // Create the object of the class UserData jclass userDataClass = env->FindClass("com/baeldung/jni/UserData"); jobject newUserData = env->AllocObject(userDataClass); // Get the UserData fields to be set jfieldID nameField = env->GetFieldID(userDataClass , "name", "Ljava/lang/String;"); jfieldID balanceField = env->GetFieldID(userDataClass , "balance", "D"); env->SetObjectField(newUserData, nameField, name); env->SetDoubleField(newUserData, balanceField, balance); return newUserData; } JNIEXPORT jstring JNICALL Java_com_baeldung_jni_ExampleObjectsJNI_printUserData (JNIEnv *env, jobject thisObject, jobject userData) { // Find the id of the Java method to be called jclass userDataClass=env->GetObjectClass(userData); jmethodID methodId=env->GetMethodID(userDataClass, "getUserInfo", "()Ljava/lang/String;"); jstring result = (jstring)env->CallObjectMethod(userData, methodId); return result; } ``` The `jni` Rust dependency may need to be updated to account for other features.
Sign in to join this conversation.
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: Lonami/Talaria#6
There is no content yet.