jna调用原生代码——传递参数
来源:互联网 发布:网络维护员 编辑:程序博客网 时间:2024/06/06 04:47
用java做个小玩意,需要调用windows操作系统的动态链接库提供的API函数。
选来选去最终决定用jna实现调用,简单方便。
这个过程中遇到的最大障碍就是怎么传递函数的参数!
ps:原生代码在本文中指x86cpu下运行的c\c++代码。
jre也必须是32位的jre,否则可能发生不明原因的错误。
整理了一个jna与windous API(__stdcall调用约定)的库的数据类型对应表
其中值得注意的:
1:
c\c++中有无符号整数,java中没有,传递接受无符号的数据时要做转换。
例子:unsigned int xx(unsigned int);
你传递参数-1(0xffffffff),函数xx中会认为你传递的参数的值为4294967295
函数返回2147483648(0x80000000),java会认为函数返回的是-2147483648
2:
windows系统提供的api一般都有两个版本:asci 和 Unicode版本,在调用这些api时可能要明确指定调用哪个版本的api.
例如:GetClassName函数就分别有
int GetClassNameA(HWND hWnd, LPSTR IpClassName, int nMaxCount);
int GetClassNameW(HWND hWnd, LPTSTR IpClassName, int nMaxCount);
两个函数,其中的形参IpClassName就分别是asci 编码和 Unicode编码,都可以支持中文。
jna的人已经在jna-platform中定义了大部分windows API、windows数据类型。用起来很方便。
3:
windows API asci版以java的String替换本地的char。
windows API Unicode版以java的WString替换本地的wchar。
windows API 接受的字符数据默认都是用小端模式存储的,java程序中所有的字符和字符串都被utf-16be转码为java的char储存。
强烈建议严格遵循数据类型的替换表。自己实现这些转换很麻烦。
eclipse可以指定源文件的编码,但编码改变后有可能改不回来,建议保持eclipse的默认设置。
4:
c\c++的结构在java中用Structure表示,如果我想用HWND WindowFromPoint(POINT Point)这个函数,
需要在java代码文件中某接口中定义函数HWND WindowFromPoint(POINT Point);
并定义一个结构,最精简的定义为:
import java.util.ArrayList;import java.util.List;import com.sun.jna.Structure;public class POINT extends Structure{ public int x; public int y; @Override protected List<String> getFieldOrder() { // 元素的添加顺序必须与结构元素声明的顺序相同,添加的顺序一定不能写错(不管是基本变量还是结构体变量,或者是数组什么的,只需要添加名称就可以 // 这个list返回的是封装结构体中的变量名称 List<String> a = new ArrayList<String>(); a.add("x"); a.add("y"); return a; }}
注意:getFieldOrder()返回的List集合存储的字符串代表的属性的访问权限必须是public,
在本例中体现为int x; int y;的访问权限必须是public。
5:
在实际使用jna的过程中中,请严格按照表替换,否则容易出现让人恼火弱智问题。
我就曾出过一些很弱智的问题,
例如:c\c++中定义了一种BOOL类型,jna也定义了一个BOOL类,但如果java中声明BOOL类型为某函数的返回值类型,这个函数对应c\c++返回值为BOOL的函数。
调用这个函数,无论接不接收返回值,都会报错 java.lang.IllegalArgumentException: Unsupported size: 0。正确的java函数的返回值类型可以是int或 boolean。
例如:原生代码有一种与平台相关的long类型,jna也定义了一种LONG类型,这很容易混淆,但正确的匹配类型是jna的NativeLong。
如果原生代码类型没有相应的java类型替换,或者嫌麻烦不想用相应的java类型可以用数组类型代替。
java数组类型可以替换大部分的本地代码的参数的数据类型,但是相应的就必须自行完成部分大小端的转换。不推荐
jna到本地代码函数的过程中可能涉及到数据在java大端模式(BIG-ENDIAN)到x86cpu小端模式(LITTLE-ENDIAN)的相互转换。
6:
jna还可以支持函数指针和回调函数,回调函数在jan-platform中有定义。
其余的我没有用到,不做讨论。
- jna调用原生代码——传递参数
- 深入浅出JNA—快速调用原生函数
- 深入浅出JNA—快速调用原生函数
- 深入浅出JNA—快速调用原生函数
- 深入浅出JNA—快速调用原生函数
- 深入浅出JNA—快速调用原生函数
- 深入浅出JNA—快速调用原生函数
- 使用JNA,让java调用原生代码
- 深入浅出JNA—快速调用原生函数01
- JNA调用VC++代码
- 深入浅出JNA--快速调用原生函数
- 黑马程序员 函数调用 —参数传递
- JNA java调用c/c++代码
- JNA java调用c/c++代码
- Jni 参数传递与操作——(C/C++ 代码与 java 代码的互相调用)
- JNA—java调用dll最简单的方法
- android原生webview中调用JS方法并传递参数给JS遇到的问题
- 使用java代码调用exe程序 (包括参数传递)
- 登录时保存用户信息 --- NSUserDefaults的简单使用
- Shiro权限框架
- MVC 多文件上传后台接收
- HDU 1540 && POJ 2892 线段树 单点染色 区间查询
- 蓝牙PSKEY的调整
- jna调用原生代码——传递参数
- Android实现推送方式解决方案
- Oracle高级复制的同步复制的配置步骤说明
- String类成员函数的实现
- Android MediaPlayer状态图明晰注释
- 日记
- Linux下7z的使用方法
- Java 内存泄露
- 【工作精华】抵质押与贷款授信的关系