博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JNA-JNI升级版
阅读量:4046 次
发布时间:2019-05-25

本文共 2496 字,大约阅读时间需要 8 分钟。

一、概述

       JNA(Java Native Acess)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架,  功能强大,易用,类似于.NET的P/Invoke. 我们知道, 使用JNI调用.dll/.so共享类库是非常麻烦和痛苦的.如果有一个现有的.dll/.so文件, 如果使用JNI技术调用, 我们首先需要另外使用C语言写一个.dll/.so共享库,使用SUN规定的数据结构替代C语言的数据结构,调用已有的dll/so中公布的函数. 然后再在Java中载入这个适配器dll/so, 再编写Java Native函数作为dll函数中的代理. 经过2个繁琐步骤才能在Java中调用本地代码. 因此, 很少有Java程序员愿意编写dll/so库中的原生函数的Java程序, 这也使Java语言在客户端上乏善可陈. 可以说JNI是Java的一大弱点!

 

二、P/InvokeJNA

       而在.NET平台上,强大的P/Invoke技术使我们Java程序员非常羡慕. 使用P/Inovke技术, 只需要使用编写一个.NET函数,再加上一个声明的标注, 就可以直接调用dll中的函数. 不需要你再使用C语言编写dll来适配.

       现在, 不需要再羡慕.NET的P/Invoke机制了, JNA把对dll/so共享库的调用减少到了和P/Invoke相同的程度. 使用JNA, 不需要再编写适配用的.dll/.so, 只需要在Java中编写一个接口和一些代码, 作为.dll/.so的代理, 就可以在Java程序中调用dll/so.

三、快速启动:

       下载一个jar包,就可以使用JNA的强大功能方便地调用动态链接库中的C函数. 示例1:

import com.sun.jna.Library;

import com.sun.jna.Native;

import com.sun.jna.Platform;

 

public class HelloWorld {

 

       public interface CLibrary extends Library {

              String libraryName = Platform.isWindows() ? "msvcrt" : "c";

              CLibrary INSTANCE = (CLibrary)Native.loadLibrary(libraryName, 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]);

              }

       }

}

 

执行以后, 可以看到输出内容

D:\MyStudy\Java\mycode>java -cp jna.jar;. HelloWorld test adfa lkj

Hello World

Argument 0 : test

Argument 1 : adfa

Argument 2 : lkj

这里,程序的打印输出实际上是使用了msvcrt.dll这个C运行时库中的printf函数打印出上面的内容, 不需要写C代码就可以直接在Java中调用外部动态链接库中函数了!

 

示例2:

1,在VS中选择C++语言,然后选择创建一个Win32程序。 选择dll类型。

 

2,发布的C函数是:

 

#define MYLIBAPI extern "C" __declspec(dllexport

MYLIBAPI void say(wchar_t* pValue);

  

//这个函数的实现是:

 

void say(wchar_t* pValue){

    std::wcout.imbue(std::locale("chs"));

    std::wcout<<L"DLL程序说:"<<pValue<<std::endl;

}// 它需要传入一个Unicode编码的字符数组。然后在控制台上打印出一段中文字符。

 3,生成dll。然后把生成的dll文件复制到Eclipse项目中,放在项目下面。

4,在Eclipse中编写以下代码:

 

import com.sun.jna.Library;

import com.sun.jna.Native;

import com.sun.jna.WString;

 

public class TestDll1Service {

 

         public interface TestDll1 extends Library {

                   /**

                    * 当前路径是在项目下,而不是bin输出目录下。

                    */

                   TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);

                   public void say(WString value);

                  

         }

      

         /**

          * @param args

          */

         public static void main(String[] args) {

                   // TODO Auto-generated method stub

                  

                   TestDll1.INSTANCE.say(new WString("这段字符串来自JAVA程序!"));

                   System.out.println("这段话是由Java直接打印出来的.");

         }

 

}

 

5,执行这个Java类。可以看到控制台下如下输出:

DLL程序说:这段字符串来自JAVA程序!

这段话是由Java直接打印出来的.

 

6,上面一行是C语言使用C++std::wcout输出的。

下面一行是Java语言输出的。

 

 

本教程由尚硅谷教育大数据研究院出品,如需转载请注明来源。

你可能感兴趣的文章
2020年终总结
查看>>
Homebrew指令集
查看>>
React Native(一):搭建开发环境、出Hello World
查看>>
React Native(二):属性、状态
查看>>
JSX使用总结
查看>>
React Native(四):布局(使用Flexbox)
查看>>
React Native(七):Android双击Back键退出应用
查看>>
Android自定义apk名称、版本号自增
查看>>
adb command not found
查看>>
Xcode 启动页面禁用和显示
查看>>
【剑指offer】q50:树中结点的最近祖先
查看>>
二叉树的非递归遍历
查看>>
【leetcode】Reorder List (python)
查看>>
【leetcode】Linked List Cycle (python)
查看>>
【leetcode】Linked List Cycle (python)
查看>>
【leetcode】Candy(python)
查看>>
【leetcode】Clone Graph(python)
查看>>
【leetcode】Sum Root to leaf Numbers
查看>>
【leetcode】Pascal's Triangle II (python)
查看>>
java自定义容器排序的两种方法
查看>>