JNA的简单使用
来源:互联网 发布:知其雄守其雌曾国藩 编辑:程序博客网 时间:2024/05/17 00:50
以前从效率上考虑,做native调用都是通过jni实现,其中的一些障碍我想开发过jni的人都知道,比如你要复用老的代码库,为了适应Jni的机制需要再做一次封装,这其中要涉及到jni的内存管理规则,和Java代码的交互,数据类型的转换,在c/c++复杂数据类型上是很棘手的。当然这些都是可以解决的,就看个人的开发思路。
近日研究了JNA(java native access),这种机制调用dll,so相对于Jni是非常方便的,你不用再做wrapper,做到只要有头文件你想调用那个接口就声明那个接口(做过.net的人是很熟悉的),当然这种好用的模式需要你下载jna.jar这个包加入你的project,说穿了别人为你做了很多转换的工作,效率肯定没有直接调用jni高。
下面就怎么使用JNA做说明,涉及到java代码调用native、native回调java代码(回调是很有用的,存在于很多库中!)、结构体参数的使用(感谢jna.jar的开发者,如果dll,so接口是自己设计的请避免结构体、复杂数据结构!)。
我的测试环境是win7 32bit旗舰版 + ecplise + jdk1.7, jna.jar请自行下载,网上很多。
1.需要引用的类,可以根据自己的情况而定。
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Callback; // 如果是cdecl模式回调要用
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.win32.StdCallLibrary.StdCallCallback;// stdcall回调模式要用
2.在Interface中声明要调用的接口(截取的主体代码)。
// 登录接口使用的结构体java声明
public static class LoginInfo extends Structure {
public static class ByValue extends LoginInfo implements Structure.ByValue {} // 这行很重要,否则你的数据到了native中完全是乱码
public byte user[] = new byte[64];
public byte pwd[] = new byte[64];
public byte host[] = new byte[64];
public int port;
}
// 声明natvie中的接口
public interface CDeviceAPI extends Library // 如果接口是stdcall约定请使用 StdCallLibrary
{
// event call interface
interface JavaCallbackEvent extends StdCallCallback// 如果回调函数是stdcall约定使用这种模式,否则使用与之对应的
{
void CallbackEvent(int type, Pointer pUser);// Pointer转c的void*
}
int init();
int cleanup();
int GetAPIVer();
int Login(LoginInfo.ByValue info);
int Logout(int userid);
int set_event_callback(int userid, JavaCallbackEvent cbfun, Pointer pUser);
}
3.上面已经完成了部分接口的声明,下面实际的调用。
// 加载dll、so,Windows环境下直接放入工程目录下即可,like unix环境放入/lib或者usr/lib即可。
CDeviceAPI lib = (CIPCAPI)Native.loadLibrary("testlib", CDeviceAPI .class);
CDeviceAPI .JavaCallbackEvent cbEvent = new CDeviceAPI .JavaCallbackEvent() {
@Override
public void CallbackEvent(int type, Pointer pUser) {
// TODO Auto-generated method stub
System.out.println("Java layer Event=" + type);
}
};
long ver = lib.GetAPIVer();
System.out.println("ver=" + ver);
// init
lib.init();
// login data
LoginInfo.ByValue info = new LoginInfo.ByValue();
info.user = new byte[64];
for(int i=0; i < "admin".length(); i++) {
info.user[i] = (byte) "admin".charAt(i);
}
userid = lib.Login(info, 1);
System.out.println("userid=" + userid);
lib.set_event_callback(userid, cbEvent, null);// 设置回调
System.out.println("wait to connect device.");
Thread.sleep(20000);
lib.cleanup(userid);
4。以上1,2,3点就是核心代码,其实只要关注c,java/jna数据类型的转换,结构体的转换,回调,接口参数入栈的约定,开发就基本没有什么问题。
jna开发确实比jni方便,如果适合自己的项目建议使用,毕竟jni加个native api Java层就要改的麻烦没有了。
如果你的接口有很多结构体参数,那不管是jni,jna在java层表达都比较麻烦,建议使用json好些。
Java—C和操作系统数据类型的对应表
Java Type
C Type
Native Representation
boolean
int
32-bit integer (customizable)
byte
char
8-bit integer
char
wchar_t
platform-dependent
short
short
16-bit integer
int
int
32-bit integer
long
long long, __int64
64-bit integer
float
float
32-bit floating point
double
double
64-bit floating point
Buffer
Pointer
pointer
platform-dependent (32- or 64-bit pointer to memory)
<T>[] (array of primitive type)
pointer
array
32- or 64-bit pointer to memory (argument/return)
contiguous memory (struct member)
除了上面的类型,JNA还支持常见的数据类型的映射。
String
char*
NUL-terminated array (native encoding or jna.encoding
)
WString
wchar_t*
NUL-terminated array (unicode)
String[]
char**
NULL-terminated array of C strings
WString[]
wchar_t**
NULL-terminated array of wide C strings
Structure
struct*
struct
pointer to struct (argument or return) (or explicitly
)
struct by value (member of struct) (or explicitly
)
Union
union
same as Structure
Structure[]
struct[]
array of structs, contiguous in memory
Callback
<T> (*fp)()
function pointer (Java or native)
NativeMapped
varies
depends on definition
NativeLong
long
platform-dependent (32- or 64-bit integer)
PointerType
pointer
same as Pointer
- JNA的简单使用
- Java jna 使用简单小结
- JNA的使用
- JNA 的使用
- JNA的使用
- JNA的使用
- JNA的使用经历
- JNA的使用经历
- JNA的使用
- JNA的使用
- 关于使用JNA爬过的坑,JNA路径问题
- 关于JNA、JNI的使用注意
- Java使用JNA调用C的SDK
- java使用JNA调用dll的方法
- JNA简单实例
- Jna简单实例子
- JNA简单了解
- 用jna实现调用c++的dll简单示例
- Apache Math Linear Regression
- Android RecyclerView(2)——基础篇
- python 正则表达式(1)
- 绩差股成妖 妖王一日暴涨900%
- Activity的透明、半透明效果的设置transparent
- JNA的简单使用
- Linux下Weblogic创建域方法和步骤
- 在java中怎么理解“用instanceof操作符判断父类对象是否为子类的一个实例”?
- Linux下定时删除过期文件的方法
- TP 上传
- 邂逅时光,感恩岁月
- 天翼短信发送三方接口对接
- nginx rewrite if指令剖析
- Android性能优化之如何避免Overdraw