为什么要传递指针,传递数组不好吗?
其实,在C语言,传递指针的目的是为了动态分配内存空间。如果是传递数组,就必须指定数组的长度,否则直接编译不通过。
-
首先是打开Visual Studio,创建项目的时候搜索DLL,选择如下图的动态链接库(DLL)。
-
创建好项目以后,把剩下的多余的文件删除掉,仅剩下如下图的文件:
-
编写一个DLL的demo程序:
#define EXPORT __declspec(dllexport)
#include <iostream>
#include <cmath>
using namespace std;
extern "C" {
EXPORT int getArrSum(int** arr, int row, int col) {
int sum = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%d\t", arr[i][j]);
}
printf("\n");
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
sum += arr[i][j];
}
}
return sum;
}
}
-
选择Release 和 x64
-
右键项目属性,然后 配置属性 -> C/C++ -> 预编译头 ,设置为不使用预编译头。
-
右键你的项目,然后点击生成,或者重新生成。
在如下图目录生成Dll文件
-
打开IDEA并创建一个Maven项目或者SpringBoot项目。把生成的Dll文件拷贝到如下图的目录。
-
编写JnaTest01Application类
package com.example.jna_test01;
import com.sun.jna.*;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JnaTest01Application {
public interface CLibrary extends Library {
JnaTest01Application.CLibrary INSTANCE = (JnaTest01Application.CLibrary) Native.load((Platform.isWindows() ? "msvcrt" : "c"), CLibrary.class);
void printf(String format, Object... args);
}
public interface DllForJava extends Library {
//加载Dll动态链接库
DllForJava INSTANCE = (DllForJava) Native.load("src/main/java/com/example/jna_test01/dll/JNATestDLL.dll", DllForJava.class);
public int getArrSum(Pointer arr, int row, int col);
}
public static void main(String[] args) {
// SpringApplication.run(DemoApplication.class, args);
CLibrary.INSTANCE.printf("Hello, World\n");
//分配一个24字节的内存,这里准备装入3个指针,一个指针占8个字节
Pointer pointers = new Memory(24);
int pointer_size = 8;
int int_size = 4;
int row = 3;
int col = 5;
for (int i = 0; i < row; i++) {
//分配20字节的内存空间,并且该指针指向这个内存空间的首地址
Pointer pointer = new Memory(20);
for (int j = 0; j < col; j++) {
pointer.setInt(j * int_size, i * j * 2 + 1);
}
pointers.setPointer(i * pointer_size, pointer);
//这里不要释放内存
// Native.free(Pointer.nativeValue(pointer));
}
//调用Dll动态链接库内的getArrSum函数
System.out.println(DllForJava.INSTANCE.getArrSum(pointers, row, col));
System.out.println("释放内存之前,pointers地址:"+pointers);
Native.free(Pointer.nativeValue(pointers));
Pointer.nativeValue(pointers, 0);
System.out.println("释放内存之后,pointers地址:"+pointers);
}
}
- 运行结果
运行结果说明,JNA确实可以传递多维指针给C函数去做一些计算。