java 用JNA方法调用C++动态链接库
JNA(Java Native Access)框架是一个开源的Java框架,是SUN公司主导开发的,建立在经典的JNI的基础之上的一个框架。非常强大、易用,功能上类似与.NET的P/Invoke。
你只需要下载一个jar包,就可以使用JNA的强大功能方便地调用动态链接库中的C函数。
下载jna.jar
JNA例子
例子1
1,在Java项目中引入jna.jar包。
2,创建一个类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.Platform; public class HelloWorld { 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]); } } } |
3,执行,可以看到控制台中打印出了
Hello, World
但是,请注意,这个程序实际上是使用msvcrt.dll这个C运行时库中的printf函数打印出上面这些字符的。
例子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"上帝说:"<<pValue<<std::endl;
}
它需要传入一个Unicode编码的字符数组。然后在控制台上打印出一段中文字符。
3,生成dll。然后把生成的dll文件复制到Eclipse项目中,放在项目下面。
4,编写以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import com.sun.jna.Library; import com.sun.jna.Native; import com.sun.jna.WString; public class TestDll1Service { public interface TestDll1 extends Library { TestDll1 INSTANCE = (TestDll1)Native.loadLibrary( "TestDll1" , TestDll1. class ); public void say(WString value); } public TestDll1Service() { // TODO Auto-generated constructor stub } public static void main(String[] args) { // TODO Auto-generated method stub TestDll1.INSTANCE.say( new WString( "Hello World!" )); System.out.println( "HHEEH我我们无法万恶" ); } } |
5,执行这个Java类。可以看到控制台下如下输出:
上帝说:Hello World!
HHEEH我我们无法万恶
6,上面一行是C语言使用C++的std::wcout输出的。
下面一行是Java语言输出的。
JNA工作原理
JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。
原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。
JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射。你不再需要编写C动态链接库。
当然,这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。可能速度会降低几倍。但影响不大。
JNA技术难点
1,当前路径是在项目下,而不是bin输出目录下。
2,数据结构的对应关系:参见官方网站
JNA编程过程
JNA把一个dll/.so文件看做是一个Java接口。
Dll是C函数的集合、容器,这正和接口的概念吻合。
我们定义这样一个接口,
public interface TestDll1 extends Library {
TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);
public void say(WString value);
}
如果dll是以stdcall方式输出函数,那么就继承StdCallLibrary。否则就继承默认的Library接口。
接口内部需要一个公共静态常量:instance。
TestDll1 INSTANCE = (TestDll1)Native.loadLibrary("TestDll1", TestDll1.class);
通过这个常量,就可以获得这个接口的实例,从而使用接口的方法。也就是调用外部dll的函数!
注意:
1,Native.loadLibrary()函数有2个参数:
A,dll或者.so文件的名字,但不带后缀名。这符合JNI的规范,因为带了后缀名就不可以跨操作系统平台了。
搜索dll的路径是:
1)项目的根路径
2)操作系统的全局路径、
3)path指定的路径。
B,第二个参数是本接口的Class类型。
JNA通过这个Class类型,根据指定的dll/.so文件,动态创建接口的实例。
2,接口中你只需要定义你需要的函数或者公共变量,不需要的可以不定义。
public void say(WString value);
参数和返回值的类型,应该和dll中的C函数的类型一致。
这是JNA,甚至所有跨平台调用的难点。
这里,C语言的函数参数是:wchar_t*。JNA中对应的Java类型是WStirng。
JNA的不足
JNA是建立在JNI技术基础之上的一个框架。使用JNI技术,不仅可以实现Java访问C函数,也可以实现C语言调用Java代码。而JNA只能实现Java访问C函数,作为一个Java框架,自然不能实现C语言调用Java代码。此时,你还是需要使用JNI技术。
参考文献:
http://blog.csdn.net/shendl/archive/2008/12/23/3589676.aspx
https://jna.dev.java.net/
java 用JNA方法调用C++动态链接库的更多相关文章
- Java使用JNA方式调用DLL(动态链接库)(原创,装载请注明出处)
Java使用JNA调用DLL 1.准备 1.JDK环境 2.Eclipse 3.JNA包 下载JNA包: (1).JNA的Github:https://github.com/java-native-a ...
- java使用JNA框架调用dll动态库
这两天了解了一下java调用dll动态库的方法,总的有三种:JNI.JNA.JNative.其中JNA调用DLL是最方便的. ·JNI ·JNA ·JNative java使用 JNI来调用dll动态 ...
- Java RMI 远程方法调用
Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...
- Java RMI远程方法调用
RMI(远程接口调用) 1. RMI的原理: RMI系统结构,在客户端和服务器端都有几层结构. 方法调用从客户对象经占位程序(Stub).远程引用层(Remote Reference Layer)和传 ...
- Android 通过 JNI 访问 Java 字段和方法调用
在前面的两篇文章中,介绍了 Android 通过 JNI 进行基础类型.字符串和数组的相关操作,并描述了 Java 和 Native 在类型和签名之间的转换关系. 有了之前那些基础,就可以实现 Jav ...
- JAVA中native方法调用
在Java中native是关键字.它一般在本地声明,异地用C和C++来实现.它的声明有几点要注意:1)native与访问控制符前后的关系不受限制.2)必须在返回类型之前.3)它一般为非抽象类方法.4) ...
- 【Java基础】方法调用机制——MethodHandle
MethodHandle是Java7引入的一种机制,主要是为了JVM支持动态语言. 一个MethodHandle调用示例 共有方法调用 首先,演示一下最基本的MethodHandle使用. 第一步:创 ...
- Java基础--继承方法调用顺序
最近因为面试的原因,回过头来复习基础的知识,都忘光了,准备买本面试书回来啃. 我先把自己测试的结论总结写出来,以后忘记再来看看 如果b类继承自a类,在main方法中new出b的对象(不带参数),那么他 ...
- JAVA类的方法调用和变量(全套)
一.类的分类: 1.普通类 2.抽象类(含有抽象方法的类) 3.静态类(不需要实例化,就可以使用的类) 二.方法的分类: 1.私有方法(只有类的内部才可以访问的方法) 2.保护方法(只有类的内部和该该 ...
随机推荐
- spring aop配置及用例说明(3)
欢迎转载交流:http://www.cnblogs.com/shizhongtao/p/3476336.html 1.这里说一下aop的@Around标签,它提供了在方法开始和结束,都能添加用户业务逻 ...
- maven入门程序(二)
这里就使用myeclipse简单创建一个实例程序. 一.创建项目 在myeclipse中创建项目选Maven Project,然后直接下一步用默认的项目空间.在archetype中选择quicksta ...
- C++通过域名获取IP地址的方法;调试通过!
BOOL GetIpByDomainName(][],int *nCount) { WSADATA wsaData; ]; HOSTENT *pHostEnt; ; struct sockaddr_i ...
- Contest1065 - 第四届“图灵杯”NEUQ-ACM程序设计竞赛(个人赛)D拿糖果
题目描述 薯片和他的朋友薯条来到了商店,商店有n个糖果,标号依次为1,2,3....n,对应的价值为W1,W2,W3...Wn.现在薯片先拿走一个标号为a的糖果,标号小于a的糖果就被商家收回去了,然后 ...
- WiFi安全之WPA介绍
WPA,全称为Wi-Fi Protected Access,是一种保护WiFi安全的系统,实现了IEEE 802.11i的大部分标准,是一种替代WEP的过渡方案. 这个协议包含了前向兼容RC4的加密协 ...
- xamarin android——数据绑定到控件(一)
mono for android 中光标由ICursor 接口标识,该接口公开了操作结果数据集的所有方法.光标的使用非常消耗系统资源,所以不使用时应该光比光标.可以通过StartManagingCur ...
- mysql的时间函数
from_unixtime()是MySQL里的时间函数 date为需要处理的参数(该参数是Unix 时间戳),可以是字段名,也可以直接是Unix 时间戳字符串 后面的 '%Y%m%d' 主要是将返回值 ...
- hadoop下跑mapreduce程序报错
mapreduce真的是门学问,遇到的问题逼着我把它从MRv1摸索到MRv2,从年前就牵挂在心里,连过年回家的旅途上都是心情凝重,今天终于在eclipse控制台看到了job completed suc ...
- Java中的分代垃圾回收策略
一.分代GC的理论基础 分代的垃圾回收策略,是基于这样一个事实:不同的对象的生命周期是不一样的.因此,不同生命周期的对象可以采取不同的收集方式,以便提高回收效率. 在Java程序运行的过程中,会产生大 ...
- 解决backbone url请求中参数有中文,存入数据库是乱码
最近项目用到了backbone 做前后端的分离方案,遇见了中文乱码问题,解决方案总结如下: 假设需要存一条课程记录到后台 model定义如下: var AddCourse= Backbone.Mo ...