jnaerator:JNA框架下向动态库传递Java Object(即动态库JNI方式访问java对象)

本文介绍了如何通过JNA在Java和动态库之间传递对象,特别是利用JNA的OPTION_ALLOW_OBJECTS选项。示例代码展示了如何在Java中调用C动态库函数,传递并接收Java对象,从而实现Java对象与C结构体的交互。这是一个关于Java本地接口(JNI)和JNA高级用法的实例解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

熟悉JNA的童鞋都知道,通过JNA可以向动态库传递(或从动态库返回)com.sun.jna.Structure为基类的对象,在动态库一层,会把Structure解析为结构C语言的structunion,jnaerator可以将C语言定义的structunion自动生成继承Structure的 java类。
但有的时候,我们希望java层与动态库直接传递Java对象,动态库以JNI方式访问java层传递的Java对象,或直接返回java对象给java层,JNA可以实现么?
最近我就遇到了这个问题,研究了JNA的代码后,发现JNA框架默认是不是允许直接传递java对象的。但可以通过指定特定的选项实现java对象的传递。

OPTION_ALLOW_OBJECTS

JNA中在调用一个native函数时是可以指定一些特别选项的。如下是com.sun.jna.Function类的invoke系列方法的其中一个定义,其中options参数允许指定函数调用时的一些特别要求:
在这里插入图片描述
这些特别要求中就有一个我们本次任务中要用到的选项:

com.sun.jna.Library.OPTION_ALLOW_OBJECTS

该选项是个布尔值,为true时允许任何Java对象作为输入参数或返回值。只有在调用函数时显式指定OPTION_ALLOW_OBJECTS为true才生效。

示例

怎么使用OPTION_ALLOW_OBJECTS选项呢?
以下以在我的项目中的实际应用代码举例说明。

下面是我在动态库中定义的一个函数

// @param    env JNIEnv 结构,JNI方式访问Java对象必须要有它
// @param    arg 输入Java 对象
// @param    msg 输入字符串
// @return   返回Java对象
void* meg_obj_arg(void *env, void* arg, const char*msg);

下面为JNA生成的 library接口方法

	/**
	 * Original signature : <code>void* meg_obj_arg(void*, void*, const char*)</code><br>
	 * <i>native declaration : src/cpp/megauth/megauth.h:116</i>
	 */
	Pointer meg_obj_arg(Pointer env, Pointer arg, String msg);

然而我们并不能直接使用这个接口方法。因为我们无法将一个Object转为Pointer对象

正确的做法如下:

	/**
	 * JNA传递Java对象测试
	 */
	@Test
	public void testObjectArg(){
		// 创建一个map对象,将 OPTION_ALLOW_OBJECTS指定为true
		Map<String, Boolean> options = new HashMap<>();
		options.put(Library.OPTION_ALLOW_OBJECTS,Boolean.TRUE);		
		// 调用getFunction方法返回函数对象
		// 在这里,MegauthLibrary 为JNAerator生成的接口类,名字是你自己定义的哦。
		Function meg_obj_arg = MegauthLibrary.JNA_NATIVE_LIB.getFunction("meg_obj_arg");
		// 调用invoke方法,注意这里要用 com.sun.jna.JNIEnv.CURRENT 对象代替实际的动态库访问java对象所需要的JNIEnv结构
		Class<?> ret = (Class<?>) meg_obj_arg.invoke(
			/** 返回值类型 */
			Class.class,
			/** 向动态传递的输入参数,与动态中的函数定义一致 */
			new Object[]{ JNIEnv.CURRENT,new StringBuilder()} , 
			/** 调用选项 */
			options);
		System.out.printf("return %s\n",ret);
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值