JNA(八)结构体数组

前言

关于环境和dll的生成,不懂的同学可以去查看JNA(一)与JNA(二)的内容
结构体可能比较重要,大多数Java应用与共享库的交互基本是以结构体做为桥梁,这里是结构体数组示例

操作

1.C语言代码

头文件(library.h)

#ifndef CDYNAMICDEMO_LIBRARY_H
#define CDYNAMICDEMO_LIBRARY_H

#include <string.h>
#include <stdlib.h>

// 结构体
struct Student {
    char *name;
    int age;
};

// 结构体数组
int sumStudentAge(const struct Student *students, int studentCount);

void getMultiStudents(struct Student **students, int *len);

void cleanStudents(struct Student *students);

#endif //CDYNAMICDEMO_LIBRARY_H

代码文件(library.c)

#include "library.h"
#include <stdio.h>

int sumStudentAge(const struct Student *students, int studentCount) {
    int sum = 0;
    int i = 0;
    for (i = 0; i < studentCount; i++) {
        sum += students[i].age;
    }
    return sum;
}

void getMultiStudents(struct Student **students, int *len) {
    *len = 3;
    *students = malloc(sizeof(struct Student) * (*len));
    memset(*students, 0, sizeof(struct Student) * 3);
    (*students)[0].name = "张三";
    (*students)[0].age = 20;
    (*students)[1].name = "李四";
    (*students)[1].age = 30;
    (*students)[2].name = "王五";
    (*students)[2].age = 40;
}

void cleanStudents(struct Student *students) {
    printf("\n清理结构体数组内存!");
    free(students);
}

2.java代码

package com.dynamic.demo.struct;

import com.sun.jna.*;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.PointerByReference;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.util.Arrays;
import java.util.List;

public interface StructArrayLibrary extends Library {
    StructArrayLibrary INSTANCE = Native.load(Platform.isWindows() ? "libCDynamicDemo" : "", StructArrayLibrary.class);

    int sumStudentAge(Student.ByReference reference, int studentCount);

    void getMultiStudents(PointerByReference pointer, IntByReference reference);

    void cleanStudents(Pointer pointer);

    @Getter
    @Setter
    @NoArgsConstructor
    public static class Student extends Structure {
        // 引用用来往C传值
        public static class ByReference extends StructLibrary.Student implements Structure.ByReference {
        }

        // 用于接收C返回的值
        public static class ByValue extends StructLibrary.Student implements Structure.ByValue {
        }

        // 属性必须是public
        public String name;
        public int age;

        // 这里需要加一个入参是指针的构造
        public Student(Pointer pointer) {
            super(pointer);
        }

        @Override
        protected List<String> getFieldOrder() {
            // 必须重载,有哪些字段
            return Arrays.asList("name", "age");
        }
    }

    public static void main(String[] args) {
        Student.ByReference reference = new Student.ByReference();
        int count = 5;
        Student.ByReference[] array = (Student.ByReference[]) reference.toArray(5);
        for (int i = 0; i < count; i++) {
            array[i].setAge(10 + i);
        }
        int age = StructArrayLibrary.INSTANCE.sumStudentAge(reference, count);
        System.out.println("所有学生年龄之和为: " + age);

        PointerByReference pointerByReference = new PointerByReference();
        IntByReference intByReference = new IntByReference();
        StructArrayLibrary.INSTANCE.getMultiStudents(pointerByReference, intByReference);
        count = intByReference.getValue();
        System.out.println("接收到的学生数量为: " + count);

        Pointer pointer = pointerByReference.getValue();
        Student studentRef = new Student(pointer);
        // 这句不能少,否则有可能读到的数据不完整
        studentRef.read();

        Student[] students = (Student[]) studentRef.toArray(count);
        for (int i = 0; i < count; i++) {
            System.out.println("name: " + students[i].getName());
        }

        StructArrayLibrary.INSTANCE.cleanStudents(pointer);
    }
}

3.查看输出

在这里插入图片描述

总结

  1. Student类中需要增加一个指针入参的构造
  2. 引用可以通过toArray转化成数组,同时数组中的元素应该已经初始化了,因为可以直接调用而不报空指针异常
  3. 如果输出的数据存在null的情况,可以尝试调用read方法
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值