近日项目中需要用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[] 和结构体等的更多相关文章

  1. c++调用python系列(1): 结构体作为入参及返回结构体

    最近在打算用python作测试用例以便对游戏服务器进行功能测试以及压力测试; 因为服务器是用c++写的,采用的TCP协议,当前的架构是打算用python构造结构体,传送给c++层进行socket发送给 ...

  2. C语言复习:结构体

    结构体专题 01.结构体类型定义及结构体变量定义     char c1,char c2, char name[62]; int age     char name[62]; int age,char ...

  3. p/invoke碎片,对结构体的处理

    结构体的一些相关知识 可直接转换类类型,比如int类型,在托管代码和非托管代码中占据内存大小 和意义都是一个样的. 结构体封送的关键是:在托管代码和非托管代码中定义的一致性.什么是定义的一致性?包括结 ...

  4. 关于C语言结构体,指针,声明的详细讲解。——Arvin

    关于结构体的详细分析 只定义结构体 struct Student { int age; char* name; char sex;//结构体成员 };//(不要忘记分号) Student是结构体的名字 ...

  5. 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符

    [源码下载] 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 ...

  6. c语言结构体指针初始化

    今天来讨论一下C中的内存管理. 记得上周在饭桌上和同事讨论C语言的崛起时,讲到了内存管理方面 我说所有指针使用前都必须初始化,结构体中的成员指针也是一样 有人反驳说,不是吧,以前做二叉树算法时,他的左 ...

  7. C++结构体中sizeof

    说明: 结构体的sizeof值,并不是简单的将其中各元素所占字节相加,而是要考虑到存储空间的字节对齐问题.这些问题在平时编程的时候也确实不怎么用到,但在一些笔试面试题目中出是常常出现,一.解释 现代计 ...

  8. C语言结构体指针初始化(转)

    reference: https://www.cnblogs.com/losesea/archive/2012/11/15/2772526.html 今天来讨论一下C中的内存管理. 记得上周在饭桌上和 ...

  9. C 语言结构体之点运算符( . )和箭头运算符( -> )的区别

    很多时候,在对结构体进行相应的编码时,时而发现是用点运算符( . ),时而是用箭头运算符( -> ):那么这两者之间的使用有什么区别么? 相同点:两者都是二元操作符,而且右边的操作数都是成员的名 ...

随机推荐

  1. parent

    <?php class MyObject { function myMethod() { //标准功能 echo "Standard Functionality\n"; } ...

  2. 3.06课·········C#语言基础

    Main函数: static void Main(string [] args){ }程序代码需要写在Main函数的花括号内. 一.输出:Console.WriteLine("这是我的第一个 ...

  3. js常用方法(。。。。不完整)

    lastIndexOf();substring();split();slice();splice(); var s="http://www.baidu.com"; var unit ...

  4. invalid constant type: 18

    javassist 3.18以下的版本不支持在JDK1.8下运行

  5. 分享知识-快乐自己:Shrio 权限标签

    一.验证当前用户是否为"访客",即未认证(包含未记住)的用户 <shiro:guest> Hi there! Please <a href="login ...

  6. POJ 2240 Arbitrage(Floyed-Warshall算法)

    题意:给出n种货币,m种兑换比率(一种货币兑换为另一种货币的比率),判断测试用例中套汇是否可行.(套汇的意思就是在经过一系列的货币兑换之后,是否可以获利.例如:货币i→货币j→货币i,这样兑换后,是否 ...

  7. jQuery向上遍历DOM树之parents(),parent(),closest()之间的区别

    http://www.poluoluo.com/jzxy/201312/253059.html 在这个sprint中,因为要写前端UI,所以用到了jQuery,但是jQuery在向上遍历DOM树的AP ...

  8. os.path

  9. Android基于socket的群聊程序

    在网上看了好多,但是感觉不是太简单就是只能单独聊,所以就自己写了个可以群聊的,直接上代码了 一.服务器端 这里用的MyEclipse作为服务器端 MyServerScoket.java package ...

  10. 幻想乡三连A:五颜六色的幻想乡

    非常直接地构造 由于答案与生成树计数有关,所以一定要使用矩阵树定理,但这样就不能限制每种颜色的便使用的数量 我们构造$N^2$个关于$Ans_{x,y}$的方程,枚举将红色的边拆成$x$条,将蓝色的边 ...