JNA的简单使用

以前从效率上考虑,做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


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
注:下文中的 *** 代表文件名中的版本号。 # 【jna-***.jar中文文档.zip】 中包含: 中文文档:【jna-***-javadoc-API文档-中文(简体)版.zip】 jar包下载地址:【jna-***.jar下载地址(官方地址+国内镜像地址).txt】 Maven依赖:【jna-***.jar Maven依赖信息(可用于项目pom.xml).txt】 Gradle依赖:【jna-***.jar Gradle依赖信息(可用于项目build.gradle).txt】 源代码下载地址:【jna-***-sources.jar下载地址(官方地址+国内镜像地址).txt】 # 本文件关键字: jna-***.jar中文文档.zip,java,jna-***.jar,net.java.dev.jna,jna,***,com.sun.jna,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压 【jna-***.jar中文文档.zip】,再解压其中的 【jna-***-javadoc-API文档-中文(简体)版.zip】,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件; # Maven依赖: ``` <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna</artifactId> <version>***</version> </dependency> ``` # Gradle依赖: ``` Gradle: implementation group: 'net.java.dev.jna', name: 'jna', version: '***' Gradle (Short): implementation 'net.java.dev.jna:jna:***' Gradle (Kotlin): implementation("net.java.dev.jna:jna:***") ``` # 含有的 Java package(包)(此处仅列举3个): ``` com.sun.jna com.sun.jna.internal com.sun.jna.platform ...... ``` # 含有的 Java class(类)(此处仅列举3个): ``` com.sun.jna.AltCallingConvention com.sun.jna.Callback com.sun.jna.Callback.UncaughtExceptionHandler ...... ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值