首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Swig在C和java之间传递数组

用Swig在C和java之间传递数组
EN

Stack Overflow用户
提问于 2020-06-09 13:29:08
回答 1查看 333关注 0票数 0

我精通C,但不精通Java,我试图使用Swig从Java调用C。简单的调用工作正常,但我无法与carrays.iarrays_java.i方法交换数组。也没有任何完整的例子。

阿米斯特I:

代码语言:javascript
复制
%module AMItest
%{
#include "AMItest.h"
%}
%include "carrays.i"
%include "AMItest.h"

阿米斯特:

代码语言:javascript
复制
extern int AMItest(double *Array, int Start, int End);

AMItest.c

代码语言:javascript
复制
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <errno.h>
#include "AMItest.h"
int AMItest(double *Array, int Start, int End) {
    if (End<=Start) {
        fprintf(stderr, "Start must be lower than End\n");
        return EDOM;
    }
    for (int i=0; i<=End-Start; i++)
        Array[i]=sin(i/4.);
    return 0;
}

main.java:

代码语言:javascript
复制
public class main {
    public static void main(String argv[]) {
        System.loadLibrary("AMItest_swig"); // File is libAMItest_swig.so
        double[] myArray = new double[11];
        System.out.println(AMItest.AMItest(myArray, 10, 20));
        for (int i=0; i<myArray.length; i++)
            System.out.print(myArray[i] + " ");
    }
}

汇编:

代码语言:javascript
复制
$ 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
main.java:7: error: incompatible types: double[] cannot be converted to SWIGTYPE_p_double
                System.out.println(AMItest.AMItest(myArray, 10, 20));

谷歌搜索SWIGTYPE_p_* errors会导致令人惊讶的少(无益)链接。我还尝试使用arrays_java.i或将其添加到.i文件中:

代码语言:javascript
复制
%array_functions( double, double )
%include <typemaps.i>
%apply (double *OUTPUT, int, int) {(double *Array, int Start, int End)};

这是我的.i文件还是我的Java的问题?!?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-09 16:26:12

使你的精神适应。我喜欢这样:

代码语言:javascript
复制
%module AMItest
%{
#include "AMItest.h"
%}
%include "arrays_java.i"
%apply double[] {double *};
%include "AMItest.h"

有时一个C函数期望数组作为指针传递.包装它的方法之一是应用arrays_java.i库文件中的Java数组类型映射.任意大小将确保类型映射应用于所有大小的数组。您可以通过指定特定的数组大小来缩小类型地图匹配规则。现在,您可以使用纯Java数组并将其传递给C代码。

参见这里的文档:http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_unbounded_c_arrays

测试

使用您所提供的示例和上面所示的修改的as test.i,您将在调用java main时获得以下输出

代码语言:javascript
复制
0
0.0 0.24740395925452294 0.479425538604203 0.6816387600233342 0.8414709848078965 0.9489846193555862 0.9974949866040544 0.9839859468739369 0.9092974268256817 0.7780731968879213 0.5984721441039564

更有效地替代大型数组

对于由11个双元素组成的数组,您可能希望使用上面所示的方法。但是,我不想隐藏SWIG文档中显示的替代方法:

这种方法可能是使用数组的最自然的方式。但是,当使用大型数组时,会遇到性能问题,因为在将数组从Java传输到C++世界时会发生大量的元素复制。为C数组使用Java数组的另一种方法是使用备选的SWIG库文件carrays.i。这种方法可以更有效地处理大型数组,因为数组一次只访问一个元素。

您的示例需要在以下两处进行修改:

AKITest.i

代码语言:javascript
复制
%module AMItest
%{
#include "AMItest.h"
%}
%include "carrays.i"
%array_functions(double, doubleArray);
%include "AMItest.h"

那么,稍微修改一下的main.java应该是这样的:

代码语言:javascript
复制
public class main {
    public static void main(String argv[]) {
        System.loadLibrary("AMItest_swig"); // File is libAMItest_swig.so
        int size = 11;
        SWIGTYPE_p_double myArray = AMItest.new_doubleArray(size);
        AMItest.AMItest(myArray, 10, 20);
        for (int i=0; i<size; i++)
            System.out.print(AMItest.doubleArray_getitem(myArray, i) + " ");
    }
}

结果是一样的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62283805

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档