前言
关于环境和dll的生成,不懂的同学可以去查看JNA(一)与JNA(二)的内容
结构体可能比较重要,大多数Java应用与共享库的交互基本是以结构体做为桥梁,这里是结构体中包含double数组的情形
操作
1.C语言代码
头文件(library.h)
#ifndef CDYNAMICDEMO_LIBRARY_H
#define CDYNAMICDEMO_LIBRARY_H
#include <string.h>
#include <stdlib.h>
// double数组结构体
struct DoubleArrayStruct {
int size;
double *arr;
};
double sumDoubleArray(const struct DoubleArrayStruct *arrayStruct);
struct DoubleArrayStruct getDoubleArray();
void cleanDoubleArray(double *arr);
#endif //CDYNAMICDEMO_LIBRARY_H
代码文件(library.c)
#include "library.h"
#include <stdio.h>
double sumDoubleArray(const struct DoubleArrayStruct *arrayStruct) {
if (NULL == arrayStruct || arrayStruct->size == 0) {
printf("\nnull return.");
return 0;
}
double sum = 0;
for (int i = 0; i < arrayStruct->size; i++) {
double val = arrayStruct->arr[i];
sum += val;
}
return sum;
}
struct DoubleArrayStruct getDoubleArray() {
struct DoubleArrayStruct arrayStruct;
arrayStruct.size = 100;
arrayStruct.arr = malloc(sizeof(double) * arrayStruct.size);
memset(arrayStruct.arr, 0, sizeof(double) * arrayStruct.size);
for (int i = 0; i < arrayStruct.size; i++) {
arrayStruct.arr[i] = (100 + i) / 100.0;
}
return arrayStruct;
}
void cleanDoubleArray(double *arr) {
free(arr);
printf("\n释放double结构体中申请的内存!");
}
2.java代码
package com.dynamic.demo.struct;
import com.sun.jna.*;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
public interface StructDoubleArrayLibrary extends Library {
StructDoubleArrayLibrary INSTANCE = Native.load(Platform.isWindows() ? "libCDynamicDemo" : "", StructDoubleArrayLibrary.class);
double sumDoubleArray(DoubleArrayStruct.ByReference reference);
DoubleArrayStruct.ByValue getDoubleArray();
void cleanDoubleArray(Pointer pointer);
@Getter
@Setter
public static class DoubleArrayStruct extends Structure {
public static class ByReference extends DoubleArrayStruct implements Structure.ByReference {
}
public static class ByValue extends DoubleArrayStruct implements Structure.ByValue {
}
// 属性要与动态库中的名称完全一致
public int size;
// double *
public Pointer arr;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("size", "arr");
}
}
public static void main(String[] args) {
DoubleArrayStruct.ByReference ref = new DoubleArrayStruct.ByReference();
ref.setSize(10);
// 通过偏移进行设值
int nativeSize = Native.getNativeSize(Double.TYPE);
ref.setArr(new Memory(100 * nativeSize));
for (int i = 0; i < 100; i++) {
double v = (i + 100.0) / 100.0;
ref.arr.setDouble(i * nativeSize, v);
}
double value = StructDoubleArrayLibrary.INSTANCE.sumDoubleArray(ref);
System.out.println("double数组结构体求值: " + value);
StructDoubleArrayLibrary.DoubleArrayStruct.ByValue doubleArray = StructDoubleArrayLibrary.INSTANCE.getDoubleArray();
System.out.println(doubleArray.getSize());
Pointer arr = doubleArray.getArr();
for (int i = 0; i < doubleArray.getSize(); i++) {
System.out.println("元素(" + i + ")= " + arr.getDouble(nativeSize * i));
// 打印前面两个
if (i > 0) {
break;
}
}
StructDoubleArrayLibrary.INSTANCE.cleanDoubleArray(arr);
}
}
3.查看输出
总结
- 结构体中包含double类型的数组时,Java中取值是通过偏移实现的