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();
    }
}

 

posted @ 2018-01-18 14:27  冷月枫寂  阅读(3371)  评论(0编辑  收藏  举报