JNA调用C语言动态链接库

最新因为项目需要,学习了一下JNA框架,在这里记录一下学习和使用心得,给大家分享,希望能帮助新手。

本文主要讲解如何使用JNA框架轻松调用C语言动态链接库,如何使用JNA模拟C语言参数(例如数组、指针等)。

JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。

JNA官网地址:https://github.com/twall/jna

官网上有很多例子和学习入门教程,建议认真阅读,很有帮助,比自己网络上到处搜索效果好多了。

Maven项目引入JNA:

  1. <!--Java JNA -->  
  2. <dependency>  
  3.     <groupId>net.java.dev.jna</groupId>  
  4.     <artifactId>jna</artifactId>  
  5.     <version>4.1.0</version>  
  6. </dependency>  

引入JNA:

import com.sun.jna.*;
import com.sun.jna.ptr.*;

1.构造JNA模拟类

C语言函数:

void function1(int a, int b, const unsigned char* data);

char * function2(float *  pVal, char * outString);

void function3(Rect * pRect, Rect rect);


JNA模拟:

  1. public interface MyLibTest extends Library {  
  2. //定义结构体  
  3. public static class Rect extends Structure {  
  4.         //公共字段的顺序,必须与C语言中的结构的顺序一致,否则会报错!  
  5.         public int left;  
  6.         public int top;  
  7.         public int right;  
  8.         public int bottom;  
  9.         //结构体传指针  
  10.         public static class ByReference extends Rect implements Structure.ByReference { }  
  11.         //结构体传值  
  12.         public static class ByValue extends Rect implements Structure.ByValue{ }  
  13.           
  14.         @Override  
  15.         protected List getFieldOrder() {  
  16.             return Arrays.asList(new String[]{"left""top""right""bottom"});  
  17.         }  
  18.    
  19.          //加载库文件  
  20.          MyLibTest INSTANCE = (MyLibTest) Native.loadLibrary("C:\libTest\CLib.dll",MyLibTest.class);  
  21.   
  22.          //函数模拟  
  23.          void function1(int a, int b, char[] data);  
  24.          String function2(FloatByReference fRef, char [] outString);  
  25.          void function3(Rect.ByReference pRect, Rect.ByValue rect);  
  26. }  
  27. 调用方式:  
  28. char[] arr1 = new char[数组大小];  
  29. function1(12, arr1);  
  30.   
  31. char[] arr2 = new char[数组大小];  
  32. FloatByReference fRef = new FloatByReference(0.1F);  
  33. String result = function2(fRef, arr2);  
  34. Rect.ByReference pRect = new Rect.ByReference(); //指针对象  
  35. Rect.ByValue rect =  new Rect.ByValue(); //传值对象  
  36. function3(pRect, rect);  

2.JNA模拟普通传值参数

C语言函数:

int function1(int a, float b, long c)

JNA模拟:

  1. int function1(int a, float b, long c)  

3.JNA模拟C语言数组

C语言函数:

void function1(char * data)

void function2(const unsigned char* data)

JNA模拟:

  1. void function1(char[] data) 或者 void function1(byte[] data)   
  2. void function2(char[] data) 或者 void function2(byte[] data)   

4.JNA模拟基本类型指针

JNA的ByReference有很多子类,这些类都在com.sun.jna.ptr包中:

IntByReference,LongByReference,FloatByReference,DoubleByReference,ShortByReference、ByteByReference、PointerByReference等等

从这些名字大家应该可以看出来他们的作用。

下面直接上例子吧:

C语言函数:

long function(int * a, long * b, float * c, double * d, short * e)

JNA模拟:

  1. long function(IntByReference aRef, LongByReference bRef, FloatByReference cRef,  DoubleByReference dRef,  ShortByReference eRef)  

如何构建这些对象呢?

  1. FloatByReference cRef = new FloatByReference();     //使用默认初始值(具体多少我也不知道)  
  2. FloatByReference cRef = new FloatByReference(0);   //初始值为0  

调用方法和普通参数一样:

function(..., cRef, ...);

获取结果值:

  1. float fVal = cRef.getValue();   

JNA都为我们做的很简单,不是吗?大笑

5. JNA模拟指针、指针的指针、模拟void *,void ** 等指针

C函数:

void function(int * pInt, int ** ppInt, void * pVoid, void ** ppVoid)

JNA模拟:

  1. void function(IntByReference pInt, PointerByReference ppInt, Pointer pVoid, PointerByReference ppVoid)  
  2. 调用举例:  
  3. IntByReference pInt = new IntByReference(0);  
  4. PointerByReference ppInt = new PointerByReference(Pointer.NULL); //指向指针的指针,初始化为NULL  
  5. Pointer pVoid = Pointer.NULL; //创建一个指向NULL的指针  
  6. PointerByReference ppVoid = new PointerByReference(Pointer.NULL);  
  7. 调用:function(pInt, ppInt, pVoid, ppVoid);  

(1)PointerByReference是指向指针的指针,遇到指针的指针都可以使用它来模拟,那么如何获取到它指向的指针呢?

Pointer p = ppVoid.getValue(); //获取指针

(2)如何获取指针的指针呢?

  1. Pointer p1 = ....;  
  2. PointerByReference pp1 = new PointerByReference(p1);  
  3. PointerByReference ppp1 = new PointerByReference(pp1.getPointer());  

这些操作大家可以自己做实验尝试,对于PointerByReference对象,getValue()是取值,而getPointer()是取这个指针的指针。

看着复杂,其实都很简单!JNA要比JNI好用多了。


参考学习资料:

http://blog.csdn.net/shendl/article/details/3589676

http://blog.csdn.net/shendl/article/details/3599849

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Features Automatic mapping from Java to native functions, with simple mappings for all primitive data types Runs on most platforms which support Java Automatic conversion between C and Java strings, with customizable encoding/decoding Structure and Union arguments/return values, by reference and by value Function Pointers, (callbacks from native code to Java) as arguments and/or members of a struct Auto-generated Java proxies for native function pointers By-reference (pointer-to-type) arguments Java array and NIO Buffer arguments (primitive types and pointers) as pointer-to-buffer Nested structures and arrays Wide (wchar_t-based) strings Native long support (32- or 64-bit as appropriate) Demo applications/examples Supported on 1.4 or later JVMs, including JavaME (earlier VMs may work with stubbed NIO support) Customizable marshalling/unmarshalling (argument and return value conversions) Customizable mapping from Java method to native function name, and customizable invocation to simulate C preprocessor function macros Support for automatic Windows ASCII/UNICODE function mappings Varargs support Type-safety for native pointers VM crash protection (optional) Optimized direct mapping for high-performance applications. COM support for early and late binding. COM/Typelib java code generator. Community and Support All questions should be posted to the jna-users Google group. Issues can be submitted here on Github. When posting to the mailing list, please include the following: What OS/CPU/architecture you're using (e.g. Windows 7 64-bit) Reference to your native interface definitions (i.e. C headers), if available The JNA mapping you're trying to use VM crash logs, if any Example native usage, and your attempted Java usage It's nearly impossible to indicate proper Java usage when there's no native reference to work from. For commercial support, please contact twalljava [at] java [dot] net. Using the Library Getting Started Functional Description. Mapping between Java and Native Using Pointers and Arrays Using Structures and Unions Using By-Reference Arguments Customization of Type Mapping Callbacks/Function Pointers/Closures Dynamically Typed Languages (JRuby/Jython) Platform Library Direct Method Mapping (Optimization) Frequently Asked Questions (FAQ) Avoiding Crashes Primary Documentation (JavaDoc) The definitive JNA reference is in the JavaDoc. Developers Contributing to JNA Setting up a Windows Development Environment Setting up an Android Development Environment Setting up a RaspberryPi Development Environment Setting up a Mac Development Environment Releasing JNA Publishing to Maven Central Contributing You're encouraged to contribute to JNA. Fork the code from https://github.com/java-native-access/jna and submit pull requests. For more information on setting up a development environment see Contributing to JNA. If you are interested in paid support, feel free to say so on the jna-users mailing list. Most simple questions will be answered on the list, but more complicated work, new features or target platforms can be negotiated with any of the JNA developers (this is how several of JNA's features came into being). You may even encounter other users with the same need and be able to cost share the new development. License This library is licensed under the LGPL, version 2.1 or later, and (from version 4.0 onward) the Apache Software License, version 2.0. Commercial license arrangements are negotiable. NOTE: Oracle is not sponsoring this project, even though the package name (com.sun.jna) might imply otherwise.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值