• 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();
        }
    }
  • 相关阅读:
    Replication:The replication agent has not logged a progress message in 10 minutes.
    分区管理
    获取URL最后一个 ‘/’ 之后的字符
    Replication 第四篇:事务复制中Subscriber的主键列是只读的
    窗口和窗口函数
    SQL Server 日期格式和日期操作
    约束4:唯一约束,Check约束和null
    约束3:default约束
    Merge语句中NULL的陷阱
    查询“全部”
  • 原文地址:https://www.cnblogs.com/deng-c-q/p/8310061.html
Copyright © 2020-2023  润新知