java中jna使用回调实现事件监听器——观察者模式
(1)C接口中的接口头文件
#pragma once #include <iostream> #include <vector> #include <core/core.hpp> #include <highgui/highgui.hpp> #include <imgproc/imgproc.hpp> #ifdef VIDEOPOSITION_EXPORTS #define VIDEOPOSITION_API __declspec(dllexport) #else #define VIDEOPOSITION_API __declspec(dllimport) #endif // VISION_EXPORTS using namespace std; using namespace cv; typedef void(*Callback_ColorPos)(int color, float fX,float fY); typedef void(*Callback_ImageOK)(int status); extern "C" int VIDEOPOSITION_API ColorPos(Callback_ColorPos GetColorPos,Callback_ImageOK GetImageSttus); extern "C" int VIDEOPOSITION_API OpenCamera(int index); extern "C" int VIDEOPOSITION_API CloseCamera();
我们可以看到,接口头文件中有三个函数,其中有一个函数的参数有两个回调类型。
(2)java中jna回调类的实现
package com.wxyz.scene_demonstration; import com.sun.jna.Callback; /** * 圆饼颜色和位置的回调接口 * * @author dengchaoqun * */ public interface ColorPosListener extends Callback {//定义一个接口继承自jna的Callback类,对应上述头文件中Callback_ColorPos回调 /** * 回调方法 * * @param color * 圆饼的颜色 * @param x * 圆饼的x轴坐标 * @param y * 圆饼的y轴坐标 */ public void Status(int color, float x, float y);//对应C中回调接口中的三个参数,(对应上述头文件中Callback_ColorPos回调中的三个参数)
}
(3)java回调接口的实现,实现ColorPosListener这个接口,实现Status方法,当动态库中有数据时, 数据就会传递到Status方法中的三个参数中,这样java端就可以监听动态库中的数据,并处理。
java对应动态库的接口如下
package com.wxyz.scene_demonstration; import com.sun.jna.Library; import com.sun.jna.Native; /** * 动态规整接口 * * @author dengchaoqun * */ public interface SceneDemo2API extends Library { SceneDemo2API INSTANCE = (SceneDemo2API) Native.loadLibrary("VideoPosition", SceneDemo2API.class); public int OpenCamera(int item);// 打开摄像头接口方法 public int ColorPos(ColorPosListener GetColorPos, ImageOKListener GetImage);// 回调获取数据的方法 public int CloseCamera();// 关闭摄像头的方法 }
java接口对应的实现类如下,以及使用demo如下
package com.wxyz.scene_demonstration; @SuppressWarnings("unused") public class SceneDemo2Control { private static boolean cameraStatus = true;// 相机打开的状态,默认关闭 private static final float Y_point = 80.0f;// 图像识别原点在机械臂坐标系中y轴方向的坐标值 private static final float Z_point = -312.5f;// 图像识别原点在机械臂坐标戏中z轴方向的坐标值,也就是吸圆饼的坐标值 private static final float s = 339.5f;// 圆饼数据发送点距离机械臂原点的x轴方向的距离,用于计算时间来用。 /** * 回调监听摄像头回传的圆饼数据,以及图片是否写好了的监听 * * @param listener * 监听器,用户在使用的时候需要实现一个ColorPosListener接口,当有数据返回的时候就可以实时获取动态库回传的数据 * image * 监听器,用户在使用的时候需要实现一个ImageOKListener接口,20ms拍一张图片,当图片写好后,返回1, * 可更新界面imageView * @return 状态码 该方法是一个延时的方法,在摄像头打开后,会一直执行,在这个过程中只有当摄像头关闭后才会返回-1值 */ public static int getColorPos(ColorPosListener listener, ImageOKListener image) { if (cameraStatus == false) { System.out.println("摄像头没打开,请先成功的打开摄像头!"); return -1; } else { int status = SceneDemo2API.INSTANCE.ColorPos(listener, image); return status; } } /** * 打开摄像头 * * @param item * 表示是哪一个摄像头,从0开始 * @return 打开摄像头的状态,-1表示打开失败,0表示打开成功 */ public static int openCamera(int item) { int status = SceneDemo2API.INSTANCE.OpenCamera(item); if (status == 0) { cameraStatus = true; System.out.println("摄像头打开成功!"); } else { cameraStatus = true; System.out.println("摄像头打开失败!"); } return status; } /** * 关闭摄像头的方法 * * @return 状态吗,-1表示关闭失败,0表示关闭成功 */ public static int closeCamera() { int status = SceneDemo2API.INSTANCE.CloseCamera(); if (status == 0) { cameraStatus = true; System.out.println("摄像头关闭成功!"); } else { cameraStatus = true; System.out.println("摄像头关闭失败!"); } return status; } // demo public static void main(String[] args) { openCamera(1); getColorPos(new ColorPosListener() { @Override public void Status(int color, float x, float y) { // color的对应关系,0红色,1绿色,2蓝色,3黄色,4白色,5紫色 x = Math.round(x);// 吸球点的x坐标系是固定,需要根据实际的去定位吸球的 y = Math.round(y) - Y_point; if (color == 1) {// 假定两种颜色分别是1,2 // 调用运动方法,气嘴吸饼,运动到指定的一边 } else if (color == 2) { // 调用运动方法,气嘴吸饼,运动到指定的一边 } System.out.println(x + "::" + y); } }, new ImageOKListener() { @Override public void GetImage(int imgReady) { // TODO Auto-generated method stub if (imgReady == 1) {// 图片写好了 // 更新imageView的值 } else if (imgReady == 0) {// 正在写图片 } } }); closeCamera(); } }