目录
前言
本文主要学习动态库与Java数据类型映射以及基本调用
一、数据类型映射
Native Type(C) | Size(大小) | Java Type |
char | 8-bit integer | byte |
short | 16-bit integer | short |
wchar_t | 16/32-bit character | char |
int | 32-bit integer | int |
int | boolean value | boolean |
long | 32/64-bit integer | NativeLong |
long long | 64-bit integer | long |
float | 32-bit FP | float |
double | 64-bit FP | double |
char* | C string | String |
void* | pointer | Pointer |
注:如果C语言返回的指针其占用空间是动态分配的,则需要额外添加清理函数进行清理
二、调用
1.生成dll文件
在CLion中编辑头文件(library.h),定义方法如下:
#ifndef CDYNAMICDEMO_LIBRARY_H
#define CDYNAMICDEMO_LIBRARY_H
#include <string.h>
#include <stdlib.h>
// 项目自带hello方法
void hello(void);
// 数据类型映射
char charToByte();
short shortToShort();
wchar_t wchartToChar();
int intToInt();
int intToBoolean();
long longToNativeLong();
long long longlongToLong();
float floatToFloat();
double doubleToDouble();
char *charPointerToString();
void *voidPointerToPointer();
// 清理上面的指针
void cleanVoidPointerToPointer(void *v);
#endif //CDYNAMICDEMO_LIBRARY_H
C代码文件(library.c):
#include "library.h"
#include <stdio.h>
void hello(void) {
printf("Hello, World!\n");
}
// 数据类型映射
char charToByte() {
char c = 'A';
return c;
}
// -32768 ~ 32767
short shortToShort() {
short s = 32767;
return s;
}
wchar_t wchartToChar() {
wchar_t w = L'中';
return w;
}
int intToInt() {
int i = -1;
return i;
}
int intToBoolean() {
return intToInt();
}
long longToNativeLong() {
long l = 1;
return l;
}
long long longlongToLong() {
long long ll = 11;
return ll;
}
float floatToFloat() {
float f = 3.14F;
return f;
}
double doubleToDouble() {
double d = 3.14159265;
return d;
}
char *charPointerToString() {
char *s = "Hello world!";
return s;
}
void *voidPointerToPointer(int len) {
void *v = malloc(sizeof(char) * len);
return v;
}
void cleanVoidPointerToPointer(void *v) {
free(v);
}
通过编译生成库文件:libCDynamicDemo.dll
2.Java调用
使用IDEA创建Maven项目
项目结构
Maven依赖
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
Java代码
package com.dynamic.demo.base;
import com.sun.jna.*;
public interface MappingLibrary extends Library {
MappingLibrary INSTANCE = Native.load(Platform.isWindows() ? "libCDynamicDemo" : "", MappingLibrary.class);
// 项目自带hello方法
void hello();
// 数据类型映射
char charToByte();
short shortToShort();
char wchartToChar();
int intToInt();
boolean intToBoolean();
NativeLong longToNativeLong();
long longlongToLong();
float floatToFloat();
double doubleToDouble();
String charPointerToString();
Pointer voidPointerToPointer(int len);
// 清理上面的指针
void cleanVoidPointerToPointer(Pointer pointer);
public static void main(String[] args) {
MappingLibrary.INSTANCE.hello();
System.out.println(MappingLibrary.INSTANCE.charToByte());
System.out.println(MappingLibrary.INSTANCE.shortToShort());
System.out.println(MappingLibrary.INSTANCE.wchartToChar());
System.out.println(MappingLibrary.INSTANCE.intToInt());
System.out.println(MappingLibrary.INSTANCE.intToBoolean());
System.out.println(MappingLibrary.INSTANCE.longToNativeLong());
System.out.println(MappingLibrary.INSTANCE.longlongToLong());
System.out.println(MappingLibrary.INSTANCE.floatToFloat());
System.out.println(MappingLibrary.INSTANCE.doubleToDouble());
System.out.println(MappingLibrary.INSTANCE.charPointerToString());
// 获取指针
Pointer pointer = MappingLibrary.INSTANCE.voidPointerToPointer(3);
System.out.println(pointer == null);
MappingLibrary.INSTANCE.cleanVoidPointerToPointer(pointer);
}
}
注:这里定义的是一个接口,然后main方法也写在这里了。写法各式各样,这样处理主要是为了演示方便。下面看输出
总结
1.演示了基本类型映射的使用方法
2.对指针需要额外进行清理,特别的,Java控制台的输出顺序是:Java本地代码优先输出、其次是动态库中的输出,最后是动态库中进行清理的输出(不要问为什么,偶也不是很清楚)