当前位置:网站首页>【混合编程jni 】第十一篇之JNA详情
【混合编程jni 】第十一篇之JNA详情
2022-06-26 22:01:00 【华为云】
继续JNA的了解,如果你还不知道JNA是什么,可以看下我上篇文章
函数的映射
接口映射
通过 Native.load() 加载动态库的时候,直接通过接口对应动态库的函数,
因为JNA 会创建一个代理,代理 invoke通过Library.Handler. 在导出的方法表中找倒匹配的函数。
直接映射
JNA 提供了直接注册的方式,如果有原生的,被标注为 native的函数调用。
可以直接使用Native.register() 注册你的方法
数据类型映射
基础类型直接映射,因为大小相同

使用指针和数组
原始数组参数(包括结构)由它们对应的 Java 类型表示。例如:
//原始 C 声明 void fill_buffer ( int *buf, int len); void fill_buffer ( int buf[], int len); //与数组语法相同 //等效的 JNA 映射 void fill_buffer( int [] buf, int len);注意:如果参数要由函数调用范围之外的本机函数使用,则必须使用 Memory 或 NIO 直接缓冲区。Java 原始数组提供的内存仅在函数调用期间由本机代码使用有效。
C 字符串数组(例如char* argv[]Cmain的 )可以用String[]Java 代码表示。JNA 将自动传递具有NULL最终元素的等效数组。
使用结构和联合
当函数需要指向结构的指针时,Java应该使用Structure。如果结构是按值传递或返回的,则只需对参数或返回类型类声明稍作修改即可。
定义类继承自Structure,。并且必须在FieldOrder注解或方法返回的列表中按顺序包含每个声明的字段名称getFieldOrder()。
如果函数需要结构数组(在内存中连续分配), Java 可以使用Structure[。
传入 的数组是Structure时,无需初始化数组元素(函数调用将为您分配、归零内存并分配元素)。
如果确实需要初始化数组,则应使用该Structure.toArray方法获取内存中连续的结构元素数组,然后可以根据需要对其进行初始化。
Unions 通常可以与Structures 互换,但要求您在setType方法正确传递给函数调用之前指示哪个联合字段是活动的。
如果您有特别长或复杂的结构,您可以考虑使用由 Olivier Chafik 编写的JNAerator工具,它可以为您生成 JNA 映射。
使用 ByReference 参数
当一个函数接受指向类型参数的指针时,您可以使用其中一种ByReference类型来捕获返回值,或子类化您自己的值。例如:
//原始 C 声明void allocate_buffer ( char **bufp, int * lenp);//等效的 JNA 映射void allocate_buffer(PointerByReference bufp, IntByReference lenp);// UsagePointerByReference pref = new PointerByReference();IntByReference iref = new IntByReference();lib.allocate_buffer(pref, iref);Pointer p = pref.getValue();byte[] buffer = p.getByteArray(0, iref.getValue());可以使用具有所需类型的单个元素的 Java 数组,但ByReference约定更好地传达了代码的意图。Pointer除了getByteArray()有效地作为类型转换到内存上之外,该类还提供了许多访问器方法。
PointerType可以通过从类派生来声明类型安全指针。
整点例子
1、数组 数组的例子,直接用上面的例子
c++头文件
#ifndef TESTJNA_TEST_H#define TESTJNA_TEST_H#define PDOOL_API extern "C" __declspec( dllexport )PDOOL_API int sum(int a, int b);PDOOL_API void fill_buffer(int buf[], int len);#endif //TESTJNA_TEST_Hc++ 实现
这里只是打印出所有的数组元素
#include "test.h"#include "iostream"int sum(int a ,int b){ return a +b;} void fill_buffer(int buf[], int len){ for (int i = 0;i<len;i++){ std::cout<<buf[i]; }}将上面代码生成的dll 拷贝到java项目的resource目录,
如果不会的话可以看下我之前的文章
看下java侧的实现
import com.sun.jna.Library;import com.sun.jna.Native;/** * 动态库接口 * @author xin.chong */public interface Lib extends Library { Lib INSTANCE = Native.load( "testJNA.dll", Lib.class); int sum(int a,int b); void fill_buffer(int[] buf, int len);}看下调用
/** * Hello world! * */public class App { public static void main(String[] args) { int result = Lib.INSTANCE.sum(1,3); System.out.println("恭喜,JNA 第一个程序成功 ,the result is "+ result); int[] arr = {1,2,3,4,5}; Lib.INSTANCE.fill_buffer(arr,arr.length); }}看下打印结果

数组调用还是简单的,当然这只是基础类型的数组,复杂的后面会讲,继续!
2、结构体
结构体属于复杂的自定义结构,所以处理起来还是比较麻烦,下面一起看下在Java中如何模拟结构体的
c++ 侧 定义一个玩家结构体
#ifndef TESTJNA_TEST_H#define TESTJNA_TEST_H#define PDOOL_API extern "C" __declspec( dllexport ) struct PlayerStruct{ long id; wchar_t* name; int age;}; PDOOL_API int sum(int a, int b); PDOOL_API void fill_buffer(int buf[], int len); PDOOL_API void createPlayer(PlayerStruct* pUserStruct); #endif //TESTJNA_TEST_Hcpp 实现void createPlayer(PlayerStruct* pPlayerStruct){ std::cout<<pPlayerStruct->id <<" "<< pPlayerStruct->name <<" "<<pPlayerStruct->age;}Java侧的实现
先创建一个类继承自 Structure 和 C++ 侧进行对应映射
import com.sun.jna.Structure; import java.util.Arrays;import java.util.List; public class PlayerStruct extends Structure { public long id; public String name; public int age; public static class ByReference extends PlayerStruct implements Structure.ByReference {} public static class ByValue extends PlayerStruct implements Structure.ByValue {} @Override protected List<String> getFieldOrder() { return Arrays.asList(new String[] { "id", "name", "age"}); }}注意点:
必须要继承 Structure getFieldOrder 返回的字段列表要和C++侧保持一致,顺序不能乱,对应了c++ 侧的内存顺序 ByReference 对应c++侧的结构体指针 ByValue 是结构体的值
边栏推荐
- Hands on deep learning pytorch version 3 - Data Preprocessing
- The importance of using fonts correctly in DataWindow
- 在哪家证券公司开户最方便最安全可靠
- MATLAB and MySQL database connection and data exchange (based on ODBC)
- BN(Batch Normalization) 的理论理解以及在tf.keras中的实际应用和总结
- 【图像处理基础】基于matlab GUI图像直方图均衡化系统【含Matlab源码 1924期】
- leetcode:710. Random numbers in the blacklist [mapping thinking]
- [fundamentals of image processing] GUI image histogram equalization system based on MATLAB [including Matlab source code 1924]
- SAP Spartacus 中的依赖注入 Dependency Injection 介绍
- Unity method for setting material and shader
猜你喜欢

AI智能抠图工具--头发丝都可见

Implementation of collaborative filtering evolution version neuralcf and tensorflow2

花店橱窗布置【动态规划】

The sharp sword of API management -- eolink
![leetcode:141. Circular linked list [hash table + speed pointer]](/img/19/f918f2cff9f831d4bbc411fe1b9776.png)
leetcode:141. Circular linked list [hash table + speed pointer]

VB. Net class library (advanced version - 1)

VB. Net class library to obtain the color under the mouse in the screen (Advanced - 3)

Briefly describe the model animation function of unity

简述unity的模型动画功能

Data governance does everything
随机推荐
VB. Net class library - 4 screen shots, clipping
Which platform is the safest for buying stocks and opening accounts? Ask for sharing
股票炒股注册开户有没有什么风险?安全吗?
ICML2022 | Neurotoxin:联邦学习的持久后门
What are the accounting elements
Icml2022 | neurotoxin: a lasting back door to federal learning
leetcode:141. Circular linked list [hash table + speed pointer]
Leetcode (122) - the best time to buy and sell stocks II
聊聊我的远程工作体验 | 社区征文
Module externe unity3d anyportrait 2D Skeleton Animation
numpy中mgrid的用法
Is there any risk in registering and opening an account for stock speculation? Is it safe?
指南针能开户炒股吗?安全吗?
MATLAB与Mysql数据库连接并数据交换(基于ODBC)
网络爬虫终篇:向10万级网易云用户发送定向消息
Web crawler 2: crawl the user ID and home page address of Netease cloud music reviews
CVPR 2022 | 美团技术团队精选论文解读
leetcode:152. 乘积最大子数组【考虑两个维度的dp】
Release of dolphin scheduler video tutorial in Shangsi Valley
如何用 SAP BTP 平台上的图形建模器创建一个 OData 服务