使用Swig在C与Java间传递数组遇类型不兼容问题求助
我来帮你搞定这个SWIG调用C数组的问题——你碰到的那个incompatible types错误,核心问题出在你的.i文件没有正确配置SWIG的类型映射,导致SWIG把C的double*默认生成了SWIGTYPE_p_double封装类,而不是直接和Java的double[]做关联。
问题根源
SWIG不会自动把C的指针类型(比如double*)映射到Java的原生数组类型(double[]),它默认会生成一个SWIGTYPE_p_*的封装类来表示C指针。你之前尝试了carrays.i和arrays_java.i但配置不到位,所以类型不匹配的错误依然存在。
解决方案:修正你的AMItest.i文件
我们用arrays_java.i来告诉SWIG将C的double*参数直接映射为Java的double[],并且因为你的C函数会修改数组内容(属于输入输出双向参数),所以要使用INOUT类型映射来处理数据的双向传递。
修改后的AMItest.i内容如下:
%module AMItest %{ // SWIG需要包含的C头文件内容 #include "AMItest.h" %} // 引入arrays_java.i,它提供了Java数组与C指针的映射支持 %include "arrays_java.i" // 关键配置:将C函数中的double* Array参数映射为Java的double[](输入输出双向) %apply double INOUT[] { double *Array }; // 引入C头文件,让SWIG处理函数声明 %include "AMItest.h"
为什么之前的尝试没生效?
你之前添加的%apply (double *OUTPUT, int, int) {(double *Array, int Start, int End)};格式不正确——SWIG的%apply是针对单个参数的类型映射,而非整个参数列表。另外,你的数组既是输入(C函数需要读取数组内存空间)也是输出(C函数会修改数组内容),所以应该用INOUT而非单纯的OUTPUT。
编译运行验证
保持你原来的编译步骤不变:
$ rm -f AMItest AMItest*.java SWIG*.java *.class *.o *.a *.so *_wrap.c $ swig -java AMItest.i $ gcc -fPIC -c AMItest.c AMItest_wrap.c -I/usr/lib/jvm/java-11-openjdk-amd64/include -I/usr/lib/jvm/java-11-openjdk-amd64/include/linux $ gcc -shared AMItest.o AMItest_wrap.o -W -o libAMItest_swig.so $ javac main.java
现在运行java main,你会看到C函数修改后的数组内容被正确打印,之前的类型错误也会消失。
补充:carrays.i的替代方案
如果你更倾向于用carrays.i,需要手动在Java代码中创建SWIG管理的数组对象,再转换为原生数组,步骤如下:
- 修改
AMItest.i:
%module AMItest %{ #include "AMItest.h" %} %include "carrays.i" // 生成double数组的操作函数 %array_functions(double, doubleArray) %include "AMItest.h"
- 修改
main.java:
public class main { public static void main(String argv[]) { System.loadLibrary("AMItest_swig"); // 创建SWIG管理的double数组 SWIGTYPE_p_double myArray = AMItest.new_doubleArray(11); // 调用C函数 System.out.println(AMItest.AMItest(myArray, 10, 20)); // 将SWIG数组转换为Java原生数组 double[] javaArray = new double[11]; for (int i=0; i<11; i++) { javaArray[i] = AMItest.doubleArray_getitem(myArray, i); } // 打印结果 for (int i=0; i<javaArray.length; i++) System.out.print(javaArray[i] + " "); // 释放SWIG数组内存 AMItest.delete_doubleArray(myArray); } }
不过显然arrays_java.i的方案更简洁,直接使用Java原生数组,不需要手动管理SWIG数组的内存。
内容的提问来源于stack exchange,提问作者dargaud

