JNA/JNI

阅读数:130 评论数:0

跳转到新版页面

分类

python/Java

正文

实现Java代码调用本地C/C++ dll/so有两种方式:

1、JNI(Java Native Interface)

如果有一个现有的.dll/.so文件,使用JNI技术调用,我们首先需要使用C语言写一个库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的.dll/.so中公布的函数。

然后瑞在Java中载入这个适配器.dll/.so,再编写Java native函数作为dll中函数的代理。

经过以上两上步骤才能在Java中调用本地代码。

 

2、JNA(Java Native Access)

使用JNA,不需要再编写适配用的.dll/.so(用于windows时编译为xxx.dll,dynamic link library,用于Linux时编译为libxxx.so,shared object),只需要在Java中编写一个接口和一些代码,作为.dll/.so的代理,就可以在Java程序中调用dll/so。

jna是对jni的封装,是建立在JNI技术基础之上的一个Java类库,原来使用JNI,必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。

JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型的映射,不再需要编写C动态链接库。

(1)C Type对应到Java Type

参考:http://java-native-access.github.io/jna/5.5.0/javadoc/

(2)技术难点

跨平台、语言调用的难点,就是不同语言之间数据类型不一致造成的问题。绝大部分跨平台调用的失败,都是这个问题造成的。关于这一点,不论何种语言,何种技术方案,都无法解决这个问题。JNA也不例外。

因为C/C++的类型与Java的类型是不一样的,你必须转换类型让它们保持一致。

(3)JNA能完全替代JNI吗?

JNA是不能完全替代JNI的,JNA只能实现Java访问C函数,而JNI不仅可以实现Java访问C函数,也可以实现C语言调用Java代码。

使用示例

package com.sun.jna.examples;

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;

/** Simple example of JNA interface mapping and usage. */
public class HelloWorld {

    // This is the standard, stable way of mapping, which supports extensive
    // customization and mapping of Java to native types.

    public interface CLibrary extends Library {
        CLibrary INSTANCE = (CLibrary)
            Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"),
                               CLibrary.class);

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

(1)需要定义一个接口,继承自Library或StdCallLibrary,默认的是继承Library,如果动态库里的函数是以stdcall方式输出的,那么就继承StdCallLibrary,比如众所周知的kernel32库。

(2)接口内部需要一个公共的静态常量:INSTANCE,通过这个常量,就可以获得这个接口实例,从而使用接口的方法。

该常量通过Native.loadLibrary()这个API函数获得,该函数有两个参数:

第一个参数是动态链接库dll/so的名称,但不带.dll或.so这样的后缀,这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。搜索动态链 接库路径的顺序是:先从当前类的当前文件夹找,如果没有找到,再在工程当前文件夹下面找win32/win64文件夹,找到后搜索对应的dll文件,如果 找不到再到WINDOWS下面去搜索,再找不到就会抛异常了。比如上例中printf函数在Windows平台下所在的dll库名称是msvcrt,而在 其它平台如Linux下的so库名称是c。

第二个参数是本接口的Class类型,JNA通过这个Class类型和指定的.dll/.so文件,动态创建接口的实例,该实例由JNA通过反射自动生成。

接口中只需要定义你要用到的函数或者公共变量,注意参数返回值的类型,应该和链接库中的函数保持一致。

 

 

 




相关推荐

1、依赖 &lt;dependency&gt; &lt;groupId&gt

Java Native Interface是Java语言的本地编程接口,我们可以通过JNI实现一些用java语言不便实现的功能。 JNI开发流程主要分为以下6步: <p

<td c