You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过JNA调用返回结构体数组的C函数createArray?

问题描述

有一个C函数createArray用于创建结构体数组,函数定义如下:

int createArray(myStruct** data_array);

在C中调用时,通过传入myStruct指针的指针来获取数组,函数返回数组大小:

myStruct* data_array;
int size = createArray(&data_array);

尝试用JNA调用该函数时,JNAerator生成的包装方法为:

int createArray(myStruct.ByReference[] data_array);

但该参数实际是输出参数,不清楚应传入什么值,且认为生成的包装方法有误,怀疑参数应为PointerByReference。尝试两种调用方式均出现Invalid memory access错误:

方式一:

PointerByReference ptr = new PointerByReference();
int size = api.createArray(ptr); //Invalid memory access

方式二:

myStruct.ByReference[] array = new myStruct.ByReference[10];
Arrays.fill(stLinks, new myStruct.ByReference()); //无此步骤会报空指针异常
int size = api.createArray(array); //Invalid memory access

寻求正确的JNA调用方法。


正确的JNA调用方案

1. 修正JNA函数映射

JNAerator生成的方法签名不符合C函数的参数类型,C中的myStruct**(指针的指针,用于输出数组首地址)对应JNA的PointerByReference类型。你需要在JNA接口中重新声明函数:

int createArray(PointerByReference data_array);

2. 调用函数并解析返回的结构体数组

按照以下步骤调用并处理返回结果:

// 初始化PointerByReference,用于接收C函数输出的数组指针
PointerByReference ptrRef = new PointerByReference();
// 调用函数,获取数组大小
int arraySize = api.createArray(ptrRef);

// 从PointerByReference中取出返回的数组指针
Pointer arrayPointer = ptrRef.getValue();

// 将原生指针转换为JNA的结构体数组
myStruct[] resultArray = arrayPointer.getArray(0, arraySize, myStruct.class);

3. 内存管理注意事项

  • 如果C函数内部使用malloc等方式分配了数组内存,必须调用C端提供的内存释放函数(比如void freeArray(myStruct* array);)来释放内存,避免内存泄漏。
  • 绝对不要直接在Java中调用Pointer的释放方法,否则会导致内存错误或崩溃。

原调用失败原因分析

  • 直接使用PointerByReference调用失败,大概率是因为之前的JNA接口函数声明仍然错误,或者C函数对传入的指针有特殊要求(根据C端调用示例,应该是C函数内部分配内存后写入指针)。
  • 使用myStruct.ByReference[]的方式完全错误:C函数需要的是一个能写入指针的地址,而Java数组对象无法直接映射到C的指针指针类型,必然触发内存访问异常。

内容的提问来源于stack exchange,提问作者yannick818

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 18:30:58