JNA调用库文件

最近项目中要集成厂商的卡口摄像头,需要通过jna调用库函数接收卡口相机抓拍的过车数据。本文记录了Java调用C语言动态库(jna)的调用方式、回调函数、结构体等。
JNA全称Java Native Access,是一个建立在经典的JNI技术之上的Java开源框架,主要解决jni调用其他语言繁琐的步骤。JNI是Java Native Interface的缩写,它提供了若干的api实现了Java和其他语言的通信(主要是c&c++).
jna 官方github:https://github.com/java-native-access/jna下面来看看GettingStarted:
/**
 * GettingStarted
 * @author tangquanbin
 * @date 2018/8/28 15:39
 */
public class HelloWorld {

    /**
     * 需要定义一个接口,继承自Library 或StdCallLibrary
     * 默认的是继承Library ,如果动态链接库里的函数是以stdcall方式输出的,那么就继承StdCallLibrary
     */
    public interface CLibrary extends Library {
        /**
         * 实例化接口,从而使用接口的方法,也就是调用外部dll/so的函数。
         *
         * 第一个参数是动态链接库dll/so的名称,但不带.dll或.so这样的后缀,这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。
         * 搜索动态链 接库路径的顺序是:先从当前类的当前文件夹找,如果没有找到,再在工程当前文件夹下面找win32/win64文件夹,
         * 找到后搜索对应的dll文件,如果 找不到再到WINDOWS下面去搜索,再找不到就会抛异常了。
         * 比如上例中printf函数在Windows平台下所在的dll库名称是msvcrt,而在 其它平台如Linux下的so库名称是c。
         *
         * 第二个参数是本接口的Class类型。JNA通过这个Class类型,根据指定的.dll/.so文件,
         * 动态创建接口的实例。该实例由JNA通过反射自动生成。
         */
        CLibrary INSTANCE = (CLibrary)Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),CLibrary.class);

        /**
         * 参数和返回值的类型,应该和链接库中的函数类型保持一致。
         * @param format
         * @param args
         */
        void printf(String format, Object... args);
    }

    public static void main(String[] args) {
        CLibrary.INSTANCE.printf("Hello, World\n");
        for (int i=0;i < args.length;i++) {
            CLibrary.INSTANCE.printf("Argument %d: %s\n", i, args[i]);
        }
    }
}

jna调用的方式上面代码中的注释已经写得很清楚了,现在我们就来看看jna的函数调用、回调函数。

我们先来看看一般回调函数java的实现,其中加入了异步的思想,这也正是回调方法Callback最大的优势:

现在有一个场景,学生A、B是同学,学生A有到题不会做就ask学生B。

1.会做题的接口

/**
 * 回调方法的优势
 * 回调方法最大的优势在于,异步回调
 * @author tangquanbin
 * @date 2018/8/30 15:54
 */
public interface Slover {
    void slove();
}

2.学生B  

/**
 * @author tangquanbin
 * @date 2018/8/30 15:58
 */
public class StudentB implements Slover{

    @Override
    public void slove() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("问题解决了");
    }

}

  

3.学生A

/**
 * @author tangquanbin
 * @date 2018/8/30 15:57
 */
public class StudentA{
    public void ask(Slover slover) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                slover.slove();
            }
        }).start();
        goSomeThing();
    }
    public void goSomeThing(){
        System.out.println("StudentB,我去做其他事了");
    }
}

测试

/**
 * @author tangquanbin
 * @date 2018/09/02 22:34
 */
public class Test {
    public static void main(String[] args) {
        StudentA studentA = new StudentA();
        studentA.ask(new StudentB());
    }
}

输出:

StudentB,我去做其他事了

问题解决了

在JNA中回调方法要继承Callback或者StdCallCallback

下面这部分参考自:https://blog.csdn.net/ggmove/article/details/17377117

列如dll接口函数及回调函数类型:

typedef void (*Callback_Status)(char *station_id, char *station_ip, int status);
int Start_Server(char *ip, int port, Callback_Status fun);

java代码->回调函数声明:

public class getSDK {
	public interface Callback_Status extends StdCallCallback {
		public void Status(String station_id, String station_ip, int status);
	}
}

java代码->回调函数实现:

public class getSDK {
	public static class Status_Realize implements Callback_Status{
		public void Status(String station_id, String station_ip, int status) {
			if (status == 2) {
				GUI.Station_online(station_id, station_ip, 1, 0);
			} else if (status == 3) {
				GUI.Station_online(station_id, station_ip, 2, 0);
			}
		}
	}
}

jna调用还有一个重要的知识点:结构体Structure。时间不早了等下次再补充吧。

原文地址:https://www.cnblogs.com/tangquanbin/p/9570010.html

时间: 2024-08-30 08:27:11

JNA调用库文件的相关文章

java 调用 库文件错误查找方法

第一步首先找到 backtrace:keyword,然后找到都应的库文件 出错的地方 pc 0000088b  /system/lib/libNDK_04.so (SayHello+98). 08-13 17:08:28.041 I/DEBUG   (  163): backtrace: 08-13 17:08:28.041 I/DEBUG   (  163):     #00  pc 00021fc0  /system/lib/libc.so (tgkill+12) 08-13 17:08:2

copy命令及库文件至/mnt/sysroot/目录shell脚本

#!/bin/bash # #获取目标目录 target=/mnt/sysroot #命令copy函数 cmndcopy(){         #假如命令不存在,return 1         if ! which $1 &> /dev/null; then                 return 1         fi         #获取命令决定路径         cmnd=$(which --skip-alias $1)         #获取命令目录名         

VS编译器如何调用动态链接库文件

在我们日常的开发中,难免要使用别人封装的第三方库:那么接下来就跟着我一步步学习如何在VS编译器中调用第三方库吧. 我自己封装了一个简单的dll文件:函数如下所示: 头文件(.h) #ifndef _MYDLL_H #define _MYDLL_H #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif extern "C&qu

Java框架JNA调用C方法(windows链接库dll文件、linux链接库so文件)

介绍 给大家介绍一个最新的访问本机代码的Java框架-JNA. JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架. JNA项目地址:https://jna.dev.java.net/ 非常强大.易用,功能上类似与.NET的P/Invoke. 不堪回首的JNI 我们知道,使用JNI调用.dll/.so共享类库是非常非常麻烦和痛苦的. 如果有一个现有的.dll/.so文件,如果使用JNI技术调用,我们首先需要另

java调用dll或so动态库文件(c++/c)

java调用dll或so动态库文件(c++/c) 博客分类: 工作 CC#C++JavaEclipse java调用dll或so动态库文件(c++/c)开发平台:Eclipse3.3.1.1+CDT(cdt-master-4.0.3)+MinGW(MinGW-5.1.4) 一:下面是java调用dll(C++) 1:下载并安装cdt :http://www.eclipse.org/cdt/downloads.php  :选择自己eclipse 支持的cdt插件,下载,并且 通过eclipse--

android 调用c文件生成so库并调用

公司需要做一个sdk,里面需要用到别人写的c文件,第一次做,各种百度,各种学习,现在做一个小总结: 一.新建一个project:例 ExampleDemo, 包名为:com.demo.example; 二.为项目配置ndk环境: 1.下载android ndk,并解压,我的存放目录为:D:\sl\android-develop\android-ndk-r14b: 2.点击进入Project Structure 3.在弹出框中选中 SDK Location 标签,在 Android NDK Loc

LINUX下C语言编程调用其他函数、链接头文件以及库文件

LINUX下C语言编程经常需要链接其他函数,而其他函数一般都放在另外.c文件中,或者打包放在一个库文件里面,我需要在main函数中调用这些函数,主要有如下几种方法: 1.当需要调用函数的个数比较少时,可以直接在main函数中包含该文件,比如一个文件夹下包含add.c和main.c文件: 方法一: 文件add.c定义两个整数相加的函数,code如下: #include <stdio.h> #include <math.h> int add(int a,int b) { int z;

nios ii 建立库文件,并在新工程中被调用

选择Nios II Library 选择location,这样的话库文件时独立的,而如果选择 Make library depend on a BSP的话会依赖BSP,如果BSP被删除了那新工程编译时会报错. 添加c源文件和h头文件 然后build project 然后新建工程: file->Nios II Application and BSP from Template 然后在工程中添加库文件的搜索路径: 右击工程文件—>properties->展开Nios II Applicati

Linux下JNA 调用 so 库

原文:https://blog.csdn.net/withiter/article/details/8077470 博文链接:https://i.cnblogs.com/EditPosts.aspx?opt=1在linux下使用jna调用本地方法的时候,需要将C写成的程序编译为so文件 1.写一个简单test.c文件: #include<stdio.h>int add(int a,int b);int add(int a,int b){      int c = a + b ;      re