C调用Java函数得到返回值的流程图如下:

erDiagram
C -->> Java: 调用Java函数
Java -->> C: 返回结果

整个流程包括以下步骤:

  1. 在C代码中调用Java函数。
  2. 定义Java函数并编写Java代码。
  3. 将Java代码编译成字节码文件。
  4. 将字节码文件打包成Java库文件。
  5. 在C代码中引入Java库文件。
  6. 调用Java函数并获取返回值。

下面分别详细介绍每一步需要做什么,以及所需的代码和注释。

步骤1:在C代码中调用Java函数。

在C代码中通过JNI(Java Native Interface)调用Java函数,需要包含jni.h头文件,并使用JNIEnv类型的指针来调用Java函数。

#include <jni.h>

JNIEXPORT jstring JNICALL Java_com_example_MyClass_getString(JNIEnv *env, jobject obj)
{
    // 调用Java函数
    jclass cls = (*env)->GetObjectClass(env, obj);
    jmethodID mid = (*env)->GetMethodID(env, cls, "getString", "()Ljava/lang/String;");
    jstring result = (*env)->CallObjectMethod(env, obj, mid);
    
    return result;
}

步骤2:定义Java函数并编写Java代码。

在Java代码中定义一个返回字符串的函数,并添加native关键字表示该函数是本地方法。

public class MyClass {
    public native String getString();
}

步骤3:将Java代码编译成字节码文件。

使用Java编译器将Java代码编译成字节码文件,命令如下:

javac MyClass.java

步骤4:将字节码文件打包成Java库文件。

使用JNI提供的工具javah将字节码文件生成对应的头文件,命令如下:

javah -jni MyClass

这将生成名为com_example_MyClass.h的头文件。然后使用C编译器将头文件和C代码一起编译,并生成动态链接库(或静态链接库)文件,命令如下:

gcc -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libmyclass.so com_example_MyClass.c

步骤5:在C代码中引入Java库文件。

在C代码中通过System.loadLibrary()方法加载Java库文件,将其与C代码进行链接。

#include <jni.h>

JNIEXPORT jstring JNICALL Java_com_example_MyClass_getString(JNIEnv *env, jobject obj)
{
    // 加载Java库文件
    JavaVM *jvm;
    (*env)->GetJavaVM(env, &jvm);
    JNIEnv *env2;
    (*jvm)->AttachCurrentThread(jvm, (void **)&env2, NULL);
    jclass cls = (*env2)->FindClass(env2, "com/example/MyClass");
    jmethodID loadLibrary = (*env2)->GetStaticMethodID(env2, cls, "loadLibrary", "()V");
    (*env2)->CallStaticVoidMethod(env2, cls, loadLibrary);
    
    // 调用Java函数
    jclass cls = (*env2)->GetObjectClass(env2, obj);
    jmethodID mid = (*env2)->GetMethodID(env2, cls, "getString", "()Ljava/lang/String;");
    jstring result = (*env2)->CallObjectMethod(env2, obj, mid);
    
    return result;
}

步骤6:调用Java函数并获取返回值。

在C代码中调用Java函数,获取返回值。

#include <jni.h>

JNIEXPORT jstring JNICALL Java_com_example_MyClass_getString(JNIEnv *env, jobject obj)
{
    // 加载Java库文件...
    
    // 调用Java函数
    jclass cls = (*env2)->GetObjectClass(env2, obj);
    jmethodID mid = (*env2)->GetMethodID(env2, cls, "getString", "()Ljava/lang/String;");
    jstring result = (*env2)->CallObjectMethod(env2, obj, mid);
    
    // 获取返回值
    const char *str = (*env2)->GetStringUTFChars(env2, result, NULL);
    // 使用返回值...
    (*env2)->ReleaseStringUTFChars(env2, result, str);
    
    return result;
}

以上就是实现C调用Java函数得到返回值的完整流程。通过JNI,C代码可以调用Java函数并获取返回值,实现了C和Java的互操作。