从 C 调用 Java 方法(回调)

从本机代码调用 Java 方法分为两步:

  1. 使用方法名称和描述符获取带有 GetMethodID JNI 函数的方法指针;
  2. 调用此处列出的 Call*Method 函数之一。

Java 代码

/*** com.example.jni.JNIJavaCallback.java ***/

package com.example.jni;

public class JNIJavaCallback {
    static {
        System.loadLibrary("libJNI_CPP");
    }
    
    public static void main(String[] args) {
        new JNIJavaCallback().callback();
    }

    public native void callback(); 

    public static void printNum(int i) {
        System.out.println("Got int from C++: " + i);
    }
    
    public void printFloat(float i) {
        System.out.println("Got float from C++: " + i);
    }
}

C++代码

// com_example_jni_JNICppCallback.cpp

#include <iostream>
#include "com_example_jni_JNIJavaCallback.h"

using namespace std;

JNIEXPORT void JNICALL Java_com_example_jni_JNIJavaCallback_callback(JNIEnv *env, jobject jthis) {
    jclass thisClass = env->GetObjectClass(jthis);

    jmethodID printFloat = env->GetMethodID(thisClass, "printFloat", "(F)V");
    if (NULL == printFloat)
        return;
    env->CallVoidMethod(jthis, printFloat, 5.221);

    jmethodID staticPrintInt = env->GetStaticMethodID(thisClass, "printNum", "(I)V");
    if (NULL == staticPrintInt)
        return;
    env->CallVoidMethod(jthis, staticPrintInt, 17);
}

输出

从 C++得到浮点数:5.221
从 C++得到 int:17

获取描述符

使用编译的 .class 文件上的 javap 程序获取描述符(或内部类型签名 )。这是 javap -p -s com.example.jni.JNIJavaCallback 的输出: ****

Compiled from "JNIJavaCallback.java"
public class com.example.jni.JNIJavaCallback {
  static {};
    descriptor: ()V

  public com.example.jni.JNIJavaCallback();
    descriptor: ()V

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V

  public native void callback();
    descriptor: ()V

  public static void printNum(int);
    descriptor: (I)V  // <---- Needed

  public void printFloat(float);
    descriptor: (F)V  // <---- Needed
}