JNI(Java Native Interface)是Java平台提供的一种机制,允许Java代码与本地代码(通常是C/C++)相互调用。要实现从Java应用程序将数据发送回C应用程序,需要理解以下几个关键概念:
首先,在C程序中定义一个回调函数,这个函数将被Java调用:
#include <jni.h>
#include <stdio.h>
// 回调函数原型
void callback_from_java(JNIEnv *env, jobject obj, jint value) {
printf("Received from Java: %d\n", value);
}
// 全局变量存储回调函数指针
void (*g_callback)(JNIEnv*, jobject, jint) = NULL;
// 注册回调函数
void register_callback(void (*callback)(JNIEnv*, jobject, jint)) {
g_callback = callback;
}
在Java端创建一个类,包含本地方法声明:
public class DataSender {
// 本地方法声明
public native void sendDataToC(int data);
// 加载本地库
static {
System.loadLibrary("DataSender");
}
// 供C调用的方法
public static void receiveDataFromC(int data) {
System.out.println("Received from C: " + data);
}
}
在C端实现Java中声明的本地方法:
#include "DataSender.h" // 由javah生成的头文件
JNIEXPORT void JNICALL Java_DataSender_sendDataToC(JNIEnv *env, jobject obj, jint data) {
printf("Java is sending data: %d\n", data);
// 如果有注册的回调函数,调用它
if (g_callback != NULL) {
g_callback(env, obj, data);
}
}
#include <jni.h>
JavaVM *jvm;
JNIEnv *env;
void launchJVM() {
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=."; // 设置类路径
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
// 创建JVM
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
// 注册回调
register_callback(callback_from_java);
// 查找并调用Java主类
jclass cls = (*env)->FindClass(env, "DataSender");
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
(*env)->CallStaticVoidMethod(env, cls, mid, NULL);
}
sendDataToC
public class DataSender {
public native void sendDataToC(int data);
static {
System.loadLibrary("DataSender");
}
public static void main(String[] args) {
DataSender sender = new DataSender();
// 模拟发送数据到C
for (int i = 0; i < 5; i++) {
sender.sendDataToC(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void receiveDataFromC(int data) {
System.out.println("Java received from C: " + data);
}
}
#include <jni.h>
#include <stdio.h>
JavaVM *jvm;
JNIEnv *env;
void callback_from_java(JNIEnv *env, jobject obj, jint value) {
printf("C received from Java: %d\n", value);
// 可以在这里调用Java方法返回数据
jclass cls = (*env)->GetObjectClass(env, obj);
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "receiveDataFromC", "(I)V");
if (mid != NULL) {
(*env)->CallStaticVoidMethod(env, cls, mid, value * 2);
}
}
void (*g_callback)(JNIEnv*, jobject, jint) = NULL;
void register_callback(void (*callback)(JNIEnv*, jobject, jint)) {
g_callback = callback;
}
JNIEXPORT void JNICALL Java_DataSender_sendDataToC(JNIEnv *env, jobject obj, jint data) {
if (g_callback != NULL) {
g_callback(env, obj, data);
}
}
void launchJVM() {
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString = "-Djava.class.path=.";
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 1;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
register_callback(callback_from_java);
jclass cls = (*env)->FindClass(env, "DataSender");
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "main", "([Ljava/lang/String;)V");
(*env)->CallStaticVoidMethod(env, cls, mid, NULL);
}
int main() {
launchJVM();
// 销毁JVM
(*jvm)->DestroyJavaVM(jvm);
return 0;
}
这种双向通信机制适用于:
-Djava.library.path
指定库路径lib
,Windows不加javap -s
查看正确的方法签名DeleteLocalRef
释放不再需要的引用AttachCurrentThread
获取JNIEnvDetachCurrentThread
通过以上方法,您可以实现Java应用程序与C应用程序之间的双向数据通信。
没有搜到相关的文章