如何通过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
相关产品推荐
相关产品推荐

