【CSDN常见问题解答】使用JNA调用Windows动态库

来源:互联网 发布:php增删改查代码 编辑:程序博客网 时间:2024/06/05 22:33

【CSDN常见问题解答】使用JNA调用Windows动态库

标签: CSDN常见问题libraryJNAJNI
 6833人阅读 评论(1) 收藏 举报
 分类:
 

Java中调用Windows平台的动态库一般会使用JNI(Java Native Interface)还有JNA(java Native Access)。

首先解释下为什么我会选用JNA,一句话来说就是使用简单。

我们知道,使用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的一大弱点!所以我们就选择JNA来写几个简单的demo。

JNA在GitHub上的地址:https://github.com/twall/jna

需要jar包,到lib文件夹里面去下载。

下面我们开始使用JNA。

第一个例子:

[java] view plain copy
 print?
  1. import com.sun.jna.Library;  
  2. import com.sun.jna.Native;  
  3. import com.sun.jna.Platform;  
  4.   
  5. public class HelloWorld {  
  6.     public interface CLibrary extends Library {  
  7.         CLibrary INSTANCE = (CLibrary) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);  
  8.         void printf(String format, Object... args);  
  9.     }  
  10.   
  11.     public static void main(String[] args) {  
  12.         CLibrary.INSTANCE.printf("Hello World, ");  
  13.         for (int i = 0; i < args.length; i++) {  
  14.             CLibrary.INSTANCE.printf("Argument %d: %s, ", i, args[i]);  
  15.         }  
  16.     }  
  17. }  

运行上面的代码,我给main函数传递了3个参数1 2 3,打印如下:

[java] view plain copy
 print?
  1. Hello World, Argument 01, Argument 12, Argument 23,   

但是,请注意,这个程序实际上是使用msvcrt.dll这个C运行时库中的printf函数打印出上面这些字符的。是不是很简单,不需要写一行C代码,就可以直接在Java中调用外部动态链接库中的函数!

 

第二个例子:

上面那个例子使用了操作系统自带的动态链接库,现在我们再自己写一个动态链接库试试。

1,在VS中选择C++语言,然后选择创建一个Win32程序。选择dll类型。
2,发布的C函数是:


[objc] view plain copy
 print?
  1. #define MYLIBAPI extern  "C"    __declspec(dllexport )   
  2. MYLIBAPIvoid say(wchar_t* pValue);  

这个函数的实现是:

[objc] view plain copy
 print?
  1. void say(wchar_t* pValue){  
  2.     std::wcout.imbue(std::locale("chs"));  
  3.     std::wcout<<L"他说:"<<pValue<<std::endl;  
  4. }  

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

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

4,然后编写下面的类:

[java] view plain copy
 print?
  1. import com.sun.jna.Library;  
  2. import com.sun.jna.Native;  
  3. import com.sun.jna.WString;  
  4.   
  5. public class TestDll1Service {  
  6.   
  7.         public interface TestDll1 extends Library {  
  8.                   /** 
  9.  
  10.                    * 当前路径是在项目下,而不是bin输出目录下。 
  11.  
  12.                    */  
  13.   
  14.                   TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);  
  15.                   public void say(WString value);  
  16.   
  17.         }  
  18.   
  19.         public TestDll1Service() {  
  20.   
  21.         }  
  22.   
  23.    
  24.   
  25.         /** 
  26.  
  27.          * @param args 
  28.  
  29.          */  
  30.   
  31.         public static void main(String[] args) {  
  32.                   TestDll1.INSTANCE.say(new WString("Hello World!"));  
  33.                   System.out.println("你好,我是来测试的!");  
  34.         }  
  35.   
  36. }  

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

[objc] view plain copy
 print?
  1. 他说: <span style="color:black;">Hello World!</span>  

[java] view plain copy
 print?
  1. 你好,我是来测试的!  

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

原创粉丝点击