JNI调用及回调(参数传递字节数组)

本文记录了使用JNI解决Java程序控制摄像头抓拍并通过JNI回调返回字节流的过程。首先介绍了JNI的基本调用步骤,然后详细阐述了在C代码中处理回调并确保参数类型匹配的方法。通过一个实例展示了从Java到C的调用,成功接收并处理字节数组,最终形成图片文件。
摘要由CSDN通过智能技术生成

最近协助同事解决了JNI调用及回调问题,在此做个记录,备忘。

问题是这样子的:同事要开发一个java程序,用来控制摄像头的抓拍,且要通过回调字节流的方式,将抓拍的图片吐给java模块,然后再调人脸识别服务。期间遇到不少问题,最开始用JNA实现了整体功能,但是测试过程发现回调总是不稳定,照片有些时候传不回来。无耐之下,只要改用JNI再试,谁知JNI果然比JNA复杂,又是各种问题,不过还好问题都解决了,在此总结下JNI调用及回调流程。

JNI使用步骤:

1、编写Java代码,其中要注明调用DLL的native方法;

2、通过javah命令,针对java代码生成c头文件;

3、基于c头文件,编写对应的函数实现,一般通过在此实现中调用真正需要交互的dll函数;

完成这3步,基本就可以完成dll调用了。对于回调,需要在c代码中,基于jni api获取要调用的类名、方法名、参数等,特别要注意参数类型的对应关系。

实例分享:

1、编写Java类

import java.io.FileOutputStream;
import java.io.IOException;

//摄像机控制类
public class CameraCtl {
    
    //加载dll库,注意需要将库放入项目根目录,或者设置native library路径到dll目录
	static {
		System.loadLibrary("HwCameraSdk");
	}

    //映射到C的本地方法
	public native void startHwCamera();

    //C的回调方法,通过参数传递字节数组,其实是图片信息
	public void hwCameraCallback(byte[] byteAry) {
		FileOutputStream out = null;
		try {
			out = new FileOutputStream("./test3.jpg");
			out.write(byteAry);
			out.flush();
		} catch (Exception 
假设我们要在 C++ 中定义一个回调函数 `onEvent`,并且在 Java 中实现一个回调接口 `MyCallback`,我们可以通过以下步骤实现 C++ 回调方法通过 JNI 反射调用 Java 回调方法: 1. 在 C++ 中定义回调函数 `onEvent`,并通过 JNI 将其注册到 Java 中: ```c++ class MyNativeClass { public: typedef void (*CallbackFunc)(int code); static void setCallback(JNIEnv* env, jobject obj, jobject callback) { jclass cls = env->GetObjectClass(callback); if (cls == NULL) return; jmethodID method = env->GetMethodID(cls, "onEvent", "(I)V"); if (method == NULL) return; callbackFunc_ = reinterpret_cast<CallbackFunc>(method); env->DeleteLocalRef(cls); callbackObj_ = env->NewGlobalRef(callback); } static void onEvent(int code) { if (callbackFunc_ != NULL && callbackObj_ != NULL) { JNIEnv* env = getJNIEnv(); env->CallVoidMethod(callbackObj_, reinterpret_cast<jmethodID>(callbackFunc_), code); } } private: static CallbackFunc callbackFunc_; static jobject callbackObj_; }; MyNativeClass::CallbackFunc MyNativeClass::callbackFunc_ = NULL; jobject MyNativeClass::callbackObj_ = NULL; extern "C" JNIEXPORT void JNICALL Java_com_example_MyClass_setCallback(JNIEnv* env, jobject obj, jobject callback) { MyNativeClass::setCallback(env, obj, callback); } ``` 2. 在 Java 中定义回调接口 `MyCallback`: ```java public interface MyCallback { void onEvent(int code); } ``` 3. 在 Java 中实现一个类 `MyClass`,并将 C++ 回调函数注册到该类中: ```java public class MyClass { static { System.loadLibrary("mylibrary"); } private static native void setCallback(MyCallback callback); public void doSomething() { // 调用 C++ 中的 onEvent 函数,触发回调 MyNativeClass.onEvent(0); } } ``` 4. 在 Java 中实现 `MyCallback` 接口并注册到 `MyClass` 中: ```java public class MyCallbackImpl implements MyCallback { @Override public void onEvent(int code) { // 处理回调事件 } } MyClass myObject = new MyClass(); myObject.setCallback(new MyCallbackImpl()); ``` 这样,当 C++ 中调用 `onEvent` 函数时,就会触发 Java 中实现的 `onEvent` 方法,从而实现了 C++ 回调方法通过 JNI 反射调用 Java 回调方法。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值