JNA 传参char[] 和结构体等
近日项目中需要用java调用c/c++编写的dll库,所有了解到jna这个东东,下面是使用的一些经验:
一、java使用Jna需要两个jar包,eg:jna-3.5.1.jar和platform-3.5.1.jar 下载地址,添加完依赖包后把需调用的dll放到项目根目录下就是和src同级目录下

二、报错:Unable to load DLL 'xxx.dll': 找不到指定的模块,可能有一下几个问题:
1、使用的jdk和dll位数不同,64位的jdk只能调用64位的dll,32一样。
2、dll的位置放的不对(也有说放在c盘的systen32下的)
3、电脑缺少dll依赖的组件(例如我重装完系统怎么调用都不成功,最后发现缺少了Visual C++ Redistributable Packages for Visual Studio 2013这个组件 下载地址,也有可能是其他组件可以用VS的插件查看,具体请百度)
三、java-c 数据类型映射 jna操作文档 下载地址
常见的映射就不说了,这里说一下我项目中用到的:
1、char*&
//dll中
int pack_clou102(char*& sendstr) //java中接口 PointerByReference 表示指针的引用类型
public int pack_clou102(PointerByReference send); //获取send
String str = send.getValue().getString(0);
//send.getValue()获取的是一个指针 而getString(0)是获取指针的值 这里不可以用
send.getValue().toString()//会导致乱码
2、char*
//根据dll的操作来决定,官方char*对应String //但是下面这个例子中用byte[]才可以 //dll中
//UINT8是指无符号8位二进制整型 在这里映射String会出现编码问题的,所以这里用byte[]
int unpack_clou102(char* recvbuf)
{
UINT8* pbuf = (UINT8*)recvbuf;
UINT8 ucCheckSum = 0;// 校验和 。。。
} //java中
public int unpack_clou102(byte[] recvbuf);
3、传参char[]
//dll
int pack_clou102(char[20] send){
。。。
return 0;
}
//有时候会遇到dll中用char[]传字符串的,java中是用byte[],这时候可以借用“”.getbytes() //jna
byte[20] bytes = "2016-08-29 11:06:23".getbytes();
int mun = pack_clou102(bytes);
4、传参结构体 可以参考 原文地址
//DLL中
struct CompanyStruct{
long id;
wchar_t* name;
UserStruct* users[];
int count;
};
//java中
public static class CompanyStruct2 extends Structure{
public NativeLong id;
public WString name;
public UserStruct.ByReference[] users=new UserStruct.ByReference[100];
public int count;
}
//测试代码
CompanyStruct2.ByReference companyStruct2=new CompanyStruct2.ByReference();
companyStruct2.id=new NativeLong(2);
companyStruct2.name=new WString("Yahoo");
companyStruct2.count=10;
UserStruct.ByReference pUserStruct=new UserStruct.ByReference();
pUserStruct.id=new NativeLong(90);
pUserStruct.age=99;
pUserStruct.name=new WString("杨致远");
// pUserStruct.write();
for(int i=0;i<companyStruct2.count;i++){
companyStruct2.users[i]=pUserStruct;
} TestDll1.INSTANCE.sayCompany2(companyStruct2);
执行测试代码,报错了。这是怎么回事?
考察JNI 技术,我们发现Java 调用原生函数时,会把传递给原生函数的Java 数据固定
在内存中,这样原生函数才可以访问这些Java 数据。对于没有固定住的Java 对象,GC 可以
删除它,也可以移动它在内存中的位置,以使堆上的内存连续。如果原生函数访问没有被固
定住的Java 对象,就会导致调用失败。
固定住哪些java 对象,是JVM 根据原生函数调用自动判断的。而上面的CompanyStruct2
结构体中的一个字段是UserStruct 对象指针的数组,因此,JVM 在执行时只是固定住了
CompanyStruct2 对象的内存,而没有固定住users 字段引用的UserStruct 数组。因此,造成
了错误。
我们需要把users 字段引用的UserStruct 数组的所有成员也全部固定住,禁止GC 移动
或者删除。
如果我们执行了pUserStruct.write();这段代码,那么就可以成功执行上述代码。
Structure 类的write()方法会把结构体的所有字段固定住,使原生函数可以访问。
JNA 传参char[] 和结构体等的更多相关文章
- c++调用python系列(1): 结构体作为入参及返回结构体
最近在打算用python作测试用例以便对游戏服务器进行功能测试以及压力测试; 因为服务器是用c++写的,采用的TCP协议,当前的架构是打算用python构造结构体,传送给c++层进行socket发送给 ...
- C语言复习:结构体
结构体专题 01.结构体类型定义及结构体变量定义 char c1,char c2, char name[62]; int age char name[62]; int age,char ...
- p/invoke碎片,对结构体的处理
结构体的一些相关知识 可直接转换类类型,比如int类型,在托管代码和非托管代码中占据内存大小 和意义都是一个样的. 结构体封送的关键是:在托管代码和非托管代码中定义的一致性.什么是定义的一致性?包括结 ...
- 关于C语言结构体,指针,声明的详细讲解。——Arvin
关于结构体的详细分析 只定义结构体 struct Student { int age; char* name; char sex;//结构体成员 };//(不要忘记分号) Student是结构体的名字 ...
- 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符
[源码下载] 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 ...
- c语言结构体指针初始化
今天来讨论一下C中的内存管理. 记得上周在饭桌上和同事讨论C语言的崛起时,讲到了内存管理方面 我说所有指针使用前都必须初始化,结构体中的成员指针也是一样 有人反驳说,不是吧,以前做二叉树算法时,他的左 ...
- C++结构体中sizeof
说明: 结构体的sizeof值,并不是简单的将其中各元素所占字节相加,而是要考虑到存储空间的字节对齐问题.这些问题在平时编程的时候也确实不怎么用到,但在一些笔试面试题目中出是常常出现,一.解释 现代计 ...
- C语言结构体指针初始化(转)
reference: https://www.cnblogs.com/losesea/archive/2012/11/15/2772526.html 今天来讨论一下C中的内存管理. 记得上周在饭桌上和 ...
- C 语言结构体之点运算符( . )和箭头运算符( -> )的区别
很多时候,在对结构体进行相应的编码时,时而发现是用点运算符( . ),时而是用箭头运算符( -> ):那么这两者之间的使用有什么区别么? 相同点:两者都是二元操作符,而且右边的操作数都是成员的名 ...
随机推荐
- java中如何制作可双击执行的程序--jar打包工具的使用
假定当前工作目录在E盘: 1.带包编译:javac -d c:\ MyMenuDemo.java 2.DOS命令行切换到c盘,注意,这里一般切换到的是用户文件目录,需要手动切换到C盘根目录 >C ...
- VC2010编译时提示:转换到 COFF 期间失败: 文件无效或损坏
有时候新安装好VS2010后编译时就提示上述错误,罗列一下从网上查找到的几种解决方案: 方案1: 点击“项目”-->“属性”--> “清单工具”, 然后选择"输入和输出’--&g ...
- jquery获取表单元素与回显
一.获取哦表单元素 dcoument表单文本对象的集合 all[] 对所有html元素的访问 forms 返回对文档中所有form对象的引用 forms[1] 对所有form对象引用 <scri ...
- android电池(五):电池 充电IC(PM2301)驱动分析篇【转】
本文转载自:http://blog.csdn.net/xubin341719/article/details/8970363 android充电这块,有的电源管理芯片内部包含充电管理,如s5pv210 ...
- [Vue] 初识Vue-常用指令
Vue Vue是一套用于构建用户界面的渐进式框架, Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合.Vue是一个JavaScript MVVM库, 以数据驱动和组件化的思想构 ...
- Luogu-3829 [SHOI2012]信用卡凸包
这道题的转化很巧妙,可以把信用卡四个角的圆心看做平面上的点来做凸包,\(ans\)就是凸包周长加上一个圆的周长 // luogu-judger-enable-o2 #include<cmath& ...
- Guid 使用记录
Guid 使用记录; Guid 数据不能设为null 用 00000000-0000-0000-0000-000000000000 代替默认值. 实体新建时,可以赋值为 Guid.Empty 也就是 ...
- node Express安装和使用
1:在cmd命令行下执行npm install -g express,安装全局的express 2:进入需要创建项目的目录下执行express nodeExpressProject,创建express ...
- 从信用卡欺诈模型看不平衡数据分类(1)数据层面:使用过采样是主流,过采样通常使用smote,或者少数使用数据复制。过采样后模型选择RF、xgboost、神经网络能够取得非常不错的效果。(2)模型层面:使用模型集成,样本不做处理,将各个模型进行特征选择、参数调优后进行集成,通常也能够取得不错的结果。(3)其他方法:偶尔可以使用异常检测技术,IF为主
总结:不平衡数据的分类,(1)数据层面:使用过采样是主流,过采样通常使用smote,或者少数使用数据复制.过采样后模型选择RF.xgboost.神经网络能够取得非常不错的效果.(2)模型层面:使用模型 ...
- 【HDU 6428】Calculate 莫比乌斯反演+线性筛
题解 代码 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1LL&l ...