使用JNA,实现java代码调用dll程序
性能上 JNI
比 JNA
有优势,编程上 JNA
比 JNI
更方便,看情况进行取舍。针对 JNI
和 JNA
的区别,在文末会有介绍。
本次我们使用 JNA
来实现java调取 C/C++
函数。
一、常见数据类型的映射转换
C/C++类型 | Java 类型 | 原生表现 |
---|
bool | boolean | 32位(同平台有关,可定制) |
bool | byte | 如果在结构体中只能映射成byte |
char | byte | 8位整数 |
wchart_t | char | 平台依赖 |
short | short | 16位整数 |
int | int | 32位整数 |
float | float | 32位浮点数 |
double | double | 64位浮点数 |
long | NativeLong | 如果在结构体中只能映射成NativeLong |
long long,_int64 | long | 64位整数 |
const char* | String | \0结尾的字符数组 |
char** | String[] | 字符串数组 |
const wchar_t* | WString | \0结尾的数组(unicode字符串) |
wchar_t** | WString[] | 字符串数组(unicode) |
void* | Pointer | 表示指向任何东西的指针 |
char* | Pointer | 表示指向任何东西的指针 |
char*& | Pointer | 表示指向任何东西的指针 |
int& | IntByReference | 表示指向int类型的指针 |
char* | ByteByReference | 表示指向char类型的指针 |
int* | IntByReference | 表示指向int类型的指针 |
float* | FloatByReference或Pointer | 表示指向float类型的指针 |
double* | DoubleByReference或Pointer | 表示指向double类型的指针 |
| | |
char& | PointerByReference | 表示指向指针的指针 |
void ** | PointerByReference | 表示指向指针的指针 |
char** | PointerByReference | 表示指向指针的指针 |
pointer array | [] (基本类型的数组) | 32位或64位的指针 |
void** | Pointer[] | 空指针数组 |
struct*/struct | Structure | 结构体指针或者结构体 |
struct[] | Structure[] | 结构体数组,临接内存 |
void (*FP)() | Callback | 函数指针 |
union | Union | 联合,等同于结构体 |
注意点:
- Structure 子类中的公共字段的顺序,必须与C 语言中的结构的顺序一致。否则会报错!
- 在结构体中,bool不能映射成boolean,否则会引发内存访问错误。因为在C、C++中的结构体中bool只占一个字节,所以只能映射成byte。如果作为函数的返回值类型,可以映射成boolean。
- long 在结构体中不能映射成java中的long类型,只能映射成Jna的NativeLong。
- 建议使用对应的ByReference对象替代Pointer,使用Pointer有时可能会得到一个垃圾值(正常情况下两种方式结果一样),如果C中函数执行失败时没有对指针的值进行处理,使用Pointer就会得到一个垃圾值。
二、代码演示
隔了段时间整理的文档,代码有点脏,具体映射写法可以直接跳到三开始看 _
1.代码结构
E:
│ MANIFEST.MF
│ pom.xml
│
├─src
│ ├─main
│ │ ├─java
│ │ │ RankLogicGraphTest.java
│ │ │ Test.java
│ │ └─resources
│ │ └─lib11
│ │ RankLogicGraph.dll
│ │
│ └─test
│ └─java
2.Java代码——POM文件,添加依赖,引用JNA
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>3.0.9</version>
</dependency>
3.Java代码——定义接口类RankLogicGraphTest.java
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.WString;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
public interface RankLogicGraphTest extends Library {
RankLogicGraphTest INSTANCE = (RankLogicGraphTest) Native.loadLibrary("RankLogicGraph", RankLogicGraphTest.class);
class ST_MyTest extends Structure {
public int m_num;
String[] y;
}
void rankLogicGraphTest();
String rankLogicGraphAlgorithmJNA(String request);
void testChar(byte request);
void testWCharT(char request);
void testShort(short request);
void testInt(int request);
void testFloat(float request);
void testDouble(double request);
void testLong(NativeLong request);
void testString(String request);
void testConstWCharTx(WString request);
void testCharXX(String[] request);
void testWCharTXX(WString[] request);
void testVoidXX(Pointer[] request);
void testStruct(ST_MyTest request);
void testIntRef(IntByReference logicGraphInfo);
void testIntx(IntByReference logicGraphInfo);
void testCharRef(PointerByReference logicGraphInfo);
void rankLogicGraphAlgorithm(String logicGraphInfo, String[] result);
void rankLogicGraphAlgorithm(Pointer logicGraphInfo, PointerByReference result);
void rankLogicGraphReleaseResult();
void rankLogicGraphReleaseResult(PointerByReference result);
void test11(Pointer pointer, int num);
int test2(Pointer pointer);
void testNewCharXRef(Pointer ptrNewCh, int nNum);
void releasePtrRef(Pointer ptrRelease);
void testNewCharXX(PointerByReference ptrNewCh, int nNum);
void releasePtr(PointerByReference ptrRelease);
}
4.Java代码——定义测试类Test.java,java调用代码
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.WString;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import java.io.File;
public class Test {
static {
File file1 = new File("src/main/resources/lib11/RankLogicGraph.dll");
System.load(file1.getAbsolutePath());
}
public static void main(String[] args) throws InterruptedException
{
System.setProperty("jna.encoding", "GBK");
System.out.println("***************************");
String request = "";
RankLogicGraphTest.INSTANCE.rankLogicGraphTest();
RankLogicGraphTest.ST_MyTest ssss = new RankLogicGraphTest.ST_MyTest();
ssss.m_num = 12;
String[] s = {"49","11"};
ssss.y = s;
RankLogicGraphTest.INSTANCE.testStruct(ssss);
System.out.println("-------------");
String ss = RankLogicGraphTest.INSTANCE.rankLogicGraphAlgorithmJNA(request);
System.out.println("rankLogicGraphAlgorithmJNA 返回:" + ss.length() + "---" + ss);
byte b = 97;
RankLogicGraphTest.INSTANCE.testChar(b);
}
}
注意点:
- 注1和注2处,RankLogicGraph 必须和引用的dll名称 保持一致,否则无法找到RankLogicGraph.dll
5.C++头文件定义
#pragma once
#ifdef RANK_LOGIC_GRAPH_LIB
#ifdef __cplusplus
#define RANK_LOGIC_GRAPH_API extern "C" __declspec(dllexport)
#else
#define RANK_LOGIC_GRAPH_API __declspec(dllexport)
#endif
#else
#ifdef __cplusplus
#define RANK_LOGIC_GRAPH_API extern "C" __declspec(dllimport)
#else
#define RANK_LOGIC_GRAPH_API __declspec(dllimport)
#endif
#endif
#include <string>
struct ST_MyTest
{
ST_MyTest() : m_num(5), m_pCh("Struct Test!")
{
}
int m_num;
char y[50];
};
RANK_LOGIC_GRAPH_API void rankLogicGraphAlgorithm2(const std::string& logicGraphInfo, std::string& result);
RANK_LOGIC_GRAPH_API void rankLogicGraphAlgorithm(const char* logicGraphInfo, char** result);
RANK_LOGIC_GRAPH_API void rankLogicGraphReleaseResult();
RANK_LOGIC_GRAPH_API char* rankLogicGraphAlgorithmJNA(const char* logicGraphInfo);
RANK_LOGIC_GRAPH_API void rankLogicGraphTest();
RANK_LOGIC_GRAPH_API void testChar(char logicGraphInfo);
RANK_LOGIC_GRAPH_API void testWCharT(wchar_t logicGraphInfo);
RANK_LOGIC_GRAPH_API void testShort(short logicGraphInfo);
RANK_LOGIC_GRAPH_API void testInt(int logicGraphInfo);
RANK_LOGIC_GRAPH_API void testFloat(float logicGraphInfo);
RANK_LOGIC_GRAPH_API void testDouble(double logicGraphInfo);
RANK_LOGIC_GRAPH_API void testLong(long logicGraphInfo);
RANK_LOGIC_GRAPH_API void testIntRef(int& logicGraphInfo);
RANK_LOGIC_GRAPH_API void testIntx(int* logicGraphInfo);
RANK_LOGIC_GRAPH_API void testCharRef(char& logicGraphInfo);
RANK_LOGIC_GRAPH_API void testString(const char* logicGraphInfo);
RANK_LOGIC_GRAPH_API void testConstWCharTx(const wchar_t* logicGraphInfo);
RANK_LOGIC_GRAPH_API void testCharXX(char** logicGraphInfo);
RANK_LOGIC_GRAPH_API void testWCharTXX(wchar_t** logicGraphInfo);
RANK_LOGIC_GRAPH_API void testVoidX(void* logicGraphInfo);
RANK_LOGIC_GRAPH_API void testVoidXX(void** logicGraphInfo);
RANK_LOGIC_GRAPH_API void testStructX(ST_MyTest* logicGraphInfo);
RANK_LOGIC_GRAPH_API void testStruct(ST_MyTest logicGraphInfo);
RANK_LOGIC_GRAPH_API void test1(void** pHandle, int num);
RANK_LOGIC_GRAPH_API int test2(void* pHandle);
RANK_LOGIC_GRAPH_API void test11(void* pHandle, int num);
RANK_LOGIC_GRAPH_API void testNewCharXRef(char*& ptrNewCh, int nNum);
RANK_LOGIC_GRAPH_API void releasePtrRef(char*& ptrRelease);
RANK_LOGIC_GRAPH_API void testNewCharXX(char** ptrNewCh, int nNum);
RANK_LOGIC_GRAPH_API void testNewCharXX2(char** ptrNewCh, int nNum);
RANK_LOGIC_GRAPH_API void releasePtr(char** ptrRelease);
三、C++与java代码映射拆分
C/C++类型 | Java 类型 | 原生表现 |
---|
bool | boolean | 32位(同平台有关,可定制) |
void testBool(boolean request);
RANK_LOGIC_GRAPH_API void testBool(bool b);
RankLogicGraphTest.INSTANCE.testBool(true);
C/C++类型 | Java 类型 | 原生表现 |
---|
char | byte | 8位整数 |
void testChar(byte request);
RANK_LOGIC_GRAPH_API void testChar(char logicGraphInfo);
byte b = 97;
RankLogicGraphTest.INSTANCE.testChar(b);
C/C++类型 | Java 类型 | 原生表现 |
---|
wchart_t | char | 平台依赖 |
void testWCharT(char request);
RANK_LOGIC_GRAPH_API void testWCharT(wchar_t logicGraphInfo);
char c1 = 'a';
RankLogicGraphTest.INSTANCE.testWCharT(c1);
C/C++类型 | Java 类型 | 原生表现 |
---|
short | short | 16位整数 |
void testShort(short request);
RANK_LOGIC_GRAPH_API void testShort(short logicGraphInfo);
short s1 = 34;
RankLogicGraphTest.INSTANCE.testShort(s1);
C/C++类型 | Java 类型 | 原生表现 |
---|
int | int | 32位整数 |
void testInt(int request);
RANK_LOGIC_GRAPH_API void testInt(int logicGraphInfo);
int i1 = 13;
RankLogicGraphTest.INSTANCE.testInt(i1);
C/C++类型 | Java 类型 | 原生表现 |
---|
float | float | 32位浮点数 |
void testFloat(float request);
RANK_LOGIC_GRAPH_API void testFloat(float logicGraphInfo);
float f1 = 23.1f;
RankLogicGraphTest.INSTANCE.testFloat(f1);
C/C++类型 | Java 类型 | 原生表现 |
---|
double | double | 64位浮点数 |
void testDouble(double request);
RANK_LOGIC_GRAPH_API void testDouble(double logicGraphInfo);
double b1 = 123;
RankLogicGraphTest.INSTANCE.testDouble(b1);
C/C++类型 | Java 类型 | 原生表现 |
---|
long | NativeLong | |
void testLong(NativeLong request);
RANK_LOGIC_GRAPH_API void testLong(long logicGraphInfo);
NativeLong n1 = new NativeLong(124);
RankLogicGraphTest.INSTANCE.testLong(n1);
C/C++类型 | Java 类型 | 原生表现 |
---|
const char* | String | \0结尾的字符数组 |
void testString(String request);
RANK_LOGIC_GRAPH_API void testString(const char* logicGraphInfo);
String str1 = "abcd1";
RankLogicGraphTest.INSTANCE.testString(str1);
C/C++类型 | Java 类型 | 原生表现 |
---|
const wchar_t* | WString | \0结尾的数组(unicode字符串) |
void testConstWCharTx(WString request);
RANK_LOGIC_GRAPH_API void testConstWCharTx(const wchar_t* logicGraphInfo);
WString ws = new WString("qq");
RankLogicGraphTest.INSTANCE.testConstWCharTx(ws);
C/C++类型 | Java 类型 | 原生表现 |
---|
char** | String[] | 字符串数组 |
void testCharXX(String[] request);
RANK_LOGIC_GRAPH_API void testCharXX(char** logicGraphInfo);
String[] sss = {"111", "222", "333"};
RankLogicGraphTest.INSTANCE.testCharXX(sss);
C/C++类型 | Java 类型 | 原生表现 |
---|
wchar_t** | WString[] | 字符串数组(unicode) |
void testWCharTXX(WString[] request);
RANK_LOGIC_GRAPH_API void testWCharTXX(wchar_t** logicGraphInfo);
WString[] ws1 = {new WString("ss"), new WString("ww"), new WString("qq")};
RankLogicGraphTest.INSTANCE.testWCharTXX(ws1);
C/C++类型 | Java 类型 | 原生表现 |
---|
void** | Pointer[] | 空指针数组 |
void testVoidXX(Pointer[] request);
RANK_LOGIC_GRAPH_API void testVoidXX(void** logicGraphInfo);
Pointer p = new Memory(Native.getNativeSize(Integer.class));
Pointer[] ps = {p};
RankLogicGraphTest.INSTANCE.testVoidXX(ps);
C/C++类型 | Java 类型 | 原生表现 |
---|
struct*/struct | Structure | 结构体指针或者结构体 |
void testStruct(ST_MyTest request);
RANK_LOGIC_GRAPH_API void testStruct(ST_MyTest logicGraphInfo);
RankLogicGraphTest.ST_MyTest ssss = new RankLogicGraphTest.ST_MyTest();
ssss.m_num = 12;
String[] s = {"49","11"};
ssss.y = s;
RankLogicGraphTest.INSTANCE.testStruct(ssss);
C/C++类型 | Java 类型 | 原生表现 |
---|
int& | IntByReference | 表示指向int类型的指针 |
void testIntRef(IntByReference logicGraphInfo);
RANK_LOGIC_GRAPH_API void testIntRef(int& logicGraphInfo);
IntByReference pId = new IntByReference();
pId.setValue(11);
RankLogicGraphTest.INSTANCE.testIntRef(pId);
C/C++类型 | Java 类型 | 原生表现 |
---|
int* | IntByReference | 表示指向int类型的指针 |
void testIntx(IntByReference logicGraphInfo);
RANK_LOGIC_GRAPH_API void testIntx(int* logicGraphInfo);
IntByReference pId1 = new IntByReference();
pId1.setValue(22);
RankLogicGraphTest.INSTANCE.testIntx(pId);
C/C++类型 | Java 类型 | 原生表现 |
---|
char& | PointerByReference | 表示指向指针的指针 |
void testCharRef(PointerByReference logicGraphInfo);
RANK_LOGIC_GRAPH_API void testCharRef(char& logicGraphInfo);
IntByReference intByReference = new IntByReference(100);
Pointer pInt = intByReference.getPointer();
PointerByReference pointer = new PointerByReference(pInt);
RankLogicGraphTest.INSTANCE.testCharRef(pointer);
C/C++类型 | Java 类型 | 原生表现 |
---|
char** | PointerByReference | 表示指向指针的指针 |
void testNewCharXX(PointerByReference ptrNewCh);
RANK_LOGIC_GRAPH_API void testNewCharXX(char** ptrNewCh);
Pointer pPara3 = new Memory(1024);
PointerByReference pp1 = new PointerByReference(pPara3);
RankLogicGraphTest.INSTANCE.testNewCharXX(pp1);
C/C++类型 | Java 类型 | 原生表现 |
---|
char* | Pointer | 表示指向任何东西的指针 |
void testNewCharXRef(Pointer ptrNewCh);
RANK_LOGIC_GRAPH_API void testNewCharXRef(char*& ptrNewCh);
Pointer pPara2 = new Memory(1024);
RankLogicGraphTest.INSTANCE.testNewCharXRef(pPara2);
C/C++类型 | Java 类型 | 原生表现 |
---|
void* | Pointer | 表示指向任何东西的指针 |
void testP(Pointer pointer, int num);
RANK_LOGIC_GRAPH_API void test11(void* pHandle);
pPara = Pointer.NULL;
RankLogicGraphTest.INSTANCE.testP(pPara);
四、JNI
和 **JNA
**的区别:
JNI
:
JNI允许Java代码和其他语言(尤其C/C++)写的代码进行交互,只要遵守调用约定即可。首先看下JNI调用C/C++的过程,注意写程序时自下而上,调用时自上而下。步骤非常的多,很麻烦。

JNA
:
JNA框架解决了既需要编写java代码,又要编写C语言的代理方法及很多数据类型的转换的问题,它提供一组Java工具类用于在运行期动态访问系统本地共享类库而不需要编写任何Native/JNI代码。开发人员只要在一个java接口中描述目标native library的函数与结构,JNA将自动实现Java接口到native function的映射,大大降低了Java调用本体共享库的开发难度。
JNA调用C/C++的过程大致如下:

JNA
调用比 JNI
调用更方便!
JNA是建立在JNI技术基础之上的一个Java类库,它使您可以方便地使用java直接访问动态链接库中的函数。
原来使用JNI,你必须手工用C写一个动态链接库,在C语言中映射Java的数据类型。
JNA中,它提供了一个动态的C语言编写的转发器,可以自动实现Java和C的数据类型映射,你不再需要编写C动态链接库。
也许这也意味着,使用JNA技术比使用JNI技术调用动态链接库会有些微的性能损失。但总体影响不大,因为JNA也避免了JNI的一些平台配置的开销!
JNA
调用比 JNI
调用性能有损失!
总之,JNA
在编程方面比 JNI
更方便,但是性能上 JNI
比**JNA
** 有优势,看情况进行取舍。
附录:
https://blog.csdn.net/wangzhongyudie/article/details/117228932
https://www.cnblogs.com/gmhappy/p/11864037.html
https://blog.csdn.net/ctwy291314/article/details/84626829
https://blog.csdn.net/xb_2015/article/details/111462459
https://github.com/java-native-access/jna/blob/master/www/Mappings.md