一、前言

  Jna调用的示范,基本包括了Java->C基本类型的转换,指针的转换等。

   不过文章是2011年的,可能后面要查看下有什么改变。

二、原文

http://www.viaboxxsystems.de/java-interoperation-with-a-native-dll-using-jna

推荐实例阅读:http://www.eshayne.com/jnaex/index.html

三、翻译

大体翻译。

从Java调用dll,你可以选择JNI和JNA。(还有其他了.......)

关于调用转换

     首先定义接口,接口继承““com.sun.jna.Library” 或者 “com.sun.jna.win32.StdCallLibrary”.”。

 

  Java中调用如下:

  

  

  基本数据转换

  上述方法中,“returnDllVersion”方法返回一个char *(C语言),JNA框架将char *转换为Java String(Unicode)。JNA提供了大部分的JAVA/C数据类型的转换,可参见“Mapping between Java and Native“.

注:此段后为自己加的内容,可能有误。

  由于我在数据转换时涉及到了很多unsigned,signed的问题,之前基础也不好,对Java/C的数据类型就一并进行了一些学习,记录在此块。

  首先,signed和unsigned区别:最高位是否符号位,参见http://www.eefocus.com/utoo/blog/10-03/186828_7076c.html

java的基本数据类型理解:这篇是看源码分析的,简单明了。参见http://www.cnblogs.com/xiaoQLu/archive/2013/04/08/3009142.html

首先可以看出,对于Java来说大多是sighed类型的,除了java char,java char为2字节,byte才为1字节相当于C中的char。

简单的一个小表,Java的类型首字母大写无视吧......小表只是自己分析过程的一个记录......

  具体表可见JNA官方Mapping,Mapping between Java and Native.

所以,我对网上的一些对C函数中unsigned int 的有些说转成Java long或者Java int的做法不是很理解。对于存储来说,计算机存储的unsighed int就是32位,转换为Java long64位读取不会越界?转换为Java  int读取的话如果涉及到最高位符号位的,按照Java int有符号的读取怎么会正确?

  输出到共享内存

C++:
EXAMPLE_DLL bool readBufferContent(unsigned char* outbuf); Java:
boolean readBufferContent(Memory memory);

  C函数”readBufferContent"将字符串输出到内存中,Java调用这函数读取等,如果写入字符串的最大长度已知,则可如下操作:

  1.Java请求分配内存,以byte为单位

   Memory memory = new Memory(100);

  2.Java调用执行,以memory为参数

   ExampleDLL.INSTANCE.readBufferContent(memory);

  3.C++写入,返回

  4.Java读取内存,获得写入字符串

   String bufferContent = memory.getString(0);

  5.当这块内存的引用为0是,Java垃圾回收机制自动回收此空间。

int 类型输出参数:call-by-reference

C++:
EXAMPLE_DLL ResultStruct* consolidate(const short *cardTypes, int *numberOfResults); Java:
Pointer consolidate(int[] cardTypes, IntByReference numberOfResults);

  这个实例演示了如下几个问题:

1. C中第一个参数为int数组(short 16位为什么会是int数组?),JNA中提供了简单数组转换,参见JNA文档 “Pointers and Arrays“。

  2.  第二个变量为输出变量,Dll把结果写入numberOfResults变量中,参数类型为int *,传入int变量地址。JNA提供了丰富的ByReference类来实现地址传参,如“com.sun.jna.ptr.IntByReference”.Java中如下可访问该地址,获取数据。

int value = numberResults.getValue();

3. 返回为结构体指针,对于这个指针不能像IntByReference一样确定该指针指向的空间大小。

 动态数组指针

  之前的方法中,C返回数组指针,数组元素类型为结构体ResultStruct,JNA不能自动转换结构体。但是可以将C结构体转换为Java Object类,结合JNA提供的数组转换,来完成结构体数组的转换。

  我们要解决2个问题:

  1. 如何为结构体数组分配和释放动态内存?
  2. 如何构造Java Object类?

 由于在函数调用前我们无法获知数组长度,所以无法确定需要的内存大小,所以不能在JNA中分配固定大小的内存。C++使用malloc()和new()来分配heap memory,DLL中必须提供单独的freeMemory()函数来实现内存的释放。

C++:
void freeMemory(ResultStruct *arr) { if(arr) delete[] arr; } Java:
void freeMemory(Pointer p);

 由于DLL自身使用了单独的heap-Manager,Java程序不能释放这段内存,进一步讨论可参见 in a C++ forum

后面是结构体的转换等,过了一遍不翻译。

Create Java objects from array of C-structs

We map the return type of the function as a com.sun.jna.Pointer in Java. With the knowledge about the C-struct (sequence and data type of member variables), the java program can read and convert the memory content to create adequate objects. The number of elements in the array is also known (variable “numberOfResults”, see above). It is very important, to compute the offset correctly to avoid JVM-crashes for invalid memory access!

C++:
struct ResultStruct {
  unsigned short count;
char description[40];
  unsigned short average;
}; Java:
public static class ResultStruct {
  public short count;
  public String description;
  public short average;
} static ResultStruct[] fromArrayPointer(Pointer pointer, int numberResults) {
ResultStruct[] arr = new ResultStruct[numberResults];
int offset = 0;
for (int i = 0; i < numberResults; i++) {
arr[i] = fromPointer(pointer, offset);
offset += 44;
}
return arr;
} static ResultStruct fromPointer(Pointer pointer, int offset) {
  ResultStruct inst = new ResultStruct();
  inst.count = pointer.getShort(offset);
  offset += 2;
  inst.description = pointer.getString(offset);
  offset += 40;
  inst.average = pointer.getShort(offset);
  return inst;
}

Callback functions (Call a Java method from within the C++ DLL)

In places, where C gets a function pointer to call a function, this can be used to call Java methods as well. JNA offers a Callback-interface, documented in chapter “Callbacks/Closures“. The Callback class inherits form the Callback interface and contains a single method of arbitrary name and with compatible signature.

C++:
EXAMPLE_DLL void setFunction(void (*func)(char **texts, int count)); Java:
void setFunction(ExampleCallback callback); public interface ExampleCallback extends Callback {
void receive(Pointer pointerToTexts, int count);
}

Convert a char** into a String-array

Finally, a look at the signature of the “receive” method in the ExampleCallback interface. It gets a string-array in form of  a pointer to a pointer, char **. Because of the differences between C-strings and Java-strings, you should use the method Pointer.getStringArray(int,int) provided by JNA to do the conversion. No care needs to be taken of memory usage, because the memory for the strings has been allocated by the C-DLL and the call happens from inside the DLL, so the C-program is responsible to free the memory when the callback returns. The java-strings copy the memory content and are completly decoupled from the c-strings.

public void receive(Pointer pointerToTexts, int count) {
String[] texts = pointerToTexts.getStringArray(0, count);
...
}

四、小节

  long  WINAPI AutoOpenComPort(long* Port, unsigned char *ComAdr, unsigned char Baud,long *FrmHandle);

分析下我自己需要的转换,32位机。

long *:之前直接用pointer指向4字节,传参pointer.应该可以直接用intbyrefrence. 想想其实实质也没差别啊

unsigned char *:就是String, byte[]?

unsigned char:byte.

理解上是不是所有指针传参都可以用pointer完成,获取看看源码怎么实现就知道了。

 

  

【翻译】JNA调用DLL的更多相关文章

  1. 使用jna调用dll,jdk位数和dll位数的关系

    最近在学习jna,发现dll文件能能否成功调用取决于jdk位数. 32位jdk只能使用32位的dll,64位jdk只能使用64位的dll,否则位数不对应的话报的错是 "Exception i ...

  2. java 用JNA调用dll 参考文档

    1  Java调用C语言动态库(JNA方式):回调函数.结构体数组传参.结构体数组返回 2jna结构体数组  JNA结构体数组 3JNA调用C语言动态链接库学习实践总结 4 Java 通过 JNA 调 ...

  3. JNA调用DLL(入门):让你一眼就学会

    DLL(Dynamic Link Library)文件,是基于C语言的动态链接库文件,就是一些封装好的方法,打成dll格式包,供别人调用 JNA是一种能够使Java语言使调用DLL的一种技术, 首先, ...

  4. Java使用JNA调用DLL库

    Java调用DLL方法有三种,JNI.JNA.JNative, 本文为JNA JNA为使用jna.jar包,下载地址:http://www.java2s.com/Code/Jar/j/Download ...

  5. JNA调用DLL

    1.引入pom <dependency> <groupId>net.java.dev.jna</groupId> <artifactId>jna< ...

  6. java使用JNA调用dll

    1.自己搞一个dll出来.参考下面链接 http://blog.csdn.net/lqena/article/details/46357165. 2.下载jar jna-4.2.1.jar. 3.复制 ...

  7. Java 通过Jna调用dll路径问题

    调试阶段 C++ dll --> window/system32C# dll --> C:\Program Files\Java\jdk1.8.0_171\bin [jdk bin] 打包 ...

  8. Java使用JNA方式调用DLL(动态链接库)(原创,装载请注明出处)

    Java使用JNA调用DLL 1.准备 1.JDK环境 2.Eclipse 3.JNA包 下载JNA包: (1).JNA的Github:https://github.com/java-native-a ...

  9. java使用JNA框架调用dll动态库

    这两天了解了一下java调用dll动态库的方法,总的有三种:JNI.JNA.JNative.其中JNA调用DLL是最方便的. ·JNI ·JNA ·JNative java使用 JNI来调用dll动态 ...

随机推荐

  1. 2019.9.27,SAP成都研究院数字创新空间团队建设,射箭和游泳

    2019年9月27日,秋高气爽,SAP成都研究院数字创新团队全体成员又迎来了一次团队建设活动.这次的主题是:射箭. 在正式活动之前,大家先享用了一顿泰式海鲜火锅: 吃饱喝足之后,我们来到了名为&quo ...

  2. Windows环境下实现Jenkins自动化部署

    详见:https://blog.csdn.net/Try_harder_every_day/article/details/79170065 Jenkins自动化部署: 几条具体的思路:1.开发人员将 ...

  3. 【leetcode】496. Next Greater Element I

    原题 You are given two arrays (without duplicates) nums1 and nums2 where nums1's elements are subset o ...

  4. mongodb副本集和分片存储理论整理

    目录 理论概述 一.各种集群简述 二.原理 主从复制 Mongodb副本集 理论概述 一.各种集群简述 mongodb有三种集群搭建方式: 分片:sharding.指为处理大量数据,将数据分开存储,不 ...

  5. Android笔记(二十五) ListView的缓存机制与BaseAdapter

    之前接触了ListView和Adapter,Adapter将数据源和View连接起来,实际应用中,我们要显示的数据往往有很多,而屏幕只有那么大,系统只能屏幕所能显示的内容,当我们滑动屏幕,会将旧的内容 ...

  6. MOOC下载器的文档整理

    1.背景   最近学习中国大学MOOC的课程,想把课程的pdf下载下来本地保存并浏览.工具: Setup-Mooc-3.4.0.exe   但是,却发现所下载的文档在不同的文件夹里,浏览很不方便.于是 ...

  7. LESS简介与使用方法

    less 是一门 CSS 预处理语言,它扩展了 CSS 语言,增加了变量.Mixin.函数等特性,使 CSS 更易维护和扩展. 一.传统写法与 less 写法对比 1. 传统 css 写法: .con ...

  8. 个性化召回算法实践(二)——LFM算法

    LFM算法核心思想是通过隐含特征(latent factor)联系用户兴趣和物品,找出潜在的主题和分类.LFM(latent factor model)通过如下公式计算用户u对物品i的兴趣: \[ P ...

  9. java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)解决方案

    java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES) at com.mysql. ...

  10. 使用Scrapy框架爬取腾讯新闻

    昨晚没事写的爬取腾讯新闻代码,在此贴出,可以参考完善. # -*- coding: utf-8 -*- import json from scrapy import Spider from scrap ...