前言
关于环境和dll的生成,不懂的同学可以去查看JNA(一)与JNA(二)的内容
结构体可能比较重要,大多数Java应用与共享库的交互基本是以结构体做为桥梁,这里是结构体中包含string数组的情形
操作
1.C语言代码
头文件(library.h)
#ifndef CDYNAMICDEMO_LIBRARY_H
#define CDYNAMICDEMO_LIBRARY_H
#include <string.h>
#include <stdlib.h>
// 字符串数组结构体
typedef struct Teacher {
// 别名
char **alias;
// 别名数量
int num;
} Teacher;
void setTeacher(Teacher *teacher);
struct Teacher getTeacher();
void clearTeacher(Teacher teacher);
#endif //CDYNAMICDEMO_LIBRARY_H
代码文件(library.c)
#include "library.h"
#include <stdio.h>
void setTeacher(Teacher *teacher) {
int i = 0;
printf("\nalias count: %d", teacher->num);
for (; i < teacher->num; i++) {
printf("\nteacher's alia name%d: %s", i, teacher->alias[i]);
}
}
struct Teacher getTeacher() {
Teacher teacher;
teacher.num = 4;
teacher.alias = malloc(sizeof(char *) * teacher.num);
teacher.alias[0] = malloc(sizeof(char) * 4);
strcpy(teacher.alias[0], "abc");
teacher.alias[1] = malloc(sizeof(char) * 5);
strcpy(teacher.alias[1], "abcd");
teacher.alias[2] = malloc(sizeof(char) * 6);
strcpy(teacher.alias[2], "abcde");
teacher.alias[3] = malloc(sizeof(char) * 13);
strcpy(teacher.alias[3], "abcdef中文");
return teacher;
}
void clearTeacher(Teacher teacher) {
printf("\n释放teacher所申请的内存");
int num = teacher.num;
for (int i = 0; i < num; i++) {
free(teacher.alias[i]);
}
free(teacher.alias);
}
2.java代码
package com.dynamic.demo.struct;
import com.sun.jna.*;
import com.sun.jna.platform.linux.LibC;
import com.sun.jna.ptr.PointerByReference;
import lombok.Getter;
import lombok.Setter;
import java.util.Arrays;
import java.util.List;
public interface StructStringArrayLibrary extends Library {
StructStringArrayLibrary INSTANCE = Native.load(Platform.isWindows() ? "libCDynamicDemo" : "", StructStringArrayLibrary.class);
void setTeacher(Structure.ByReference reference);
Teacher.ByValue getTeacher();
void clearTeacher(Teacher.ByValue teacher);
@Getter
@Setter
static class Teacher extends Structure {
public static class ByReference extends Teacher implements Structure.ByReference {
}
public static class ByValue extends Teacher implements Structure.ByValue {
}
// char**
public Pointer alias;
public int num;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("alias", "num");
}
}
public static void main(String[] args) {
int num = 5;
String alias[] = new String[num];
alias[0] = "zhansan";
alias[1] = "lisi";
alias[2] = "wangwu";
alias[3] = "zhaoliu";
alias[4] = "钱七";
Teacher.ByReference teacher = new Teacher.ByReference();
teacher.setNum(num);
teacher.setAlias(new StringArray(alias));
StructStringArrayLibrary.INSTANCE.setTeacher(teacher);
// 获取字符串数组
Teacher.ByValue teacher1 = StructStringArrayLibrary.INSTANCE.getTeacher();
System.out.println("别名数量: " + teacher1.getNum());
Pointer alias1 = teacher1.getAlias();
String[] stringArray = alias1.getStringArray(0, teacher1.getNum());
for (String name : stringArray) {
System.out.println(name);
}
//清理
StructStringArrayLibrary.INSTANCE.clearTeacher(teacher1);
}
}
3.查看输出

总结
- 仔细观察,也可以通过ByValue的方式直接传对象到动态库中,而无需通过引用
本文介绍了如何在C语言和Java中通过结构体处理字符串数组,包括C代码中的动态内存分配和释放,以及Java中使用JNA进行跨语言通信。展示了如何通过`ByValue`方式传递对象给动态库并清理内存。
777





