【问题标题】:How do I pass arrays from Java to C++ using Swig?如何使用 Swig 将数组从 Java 传递到 C++?
【发布时间】:2010-11-12 17:12:44
【问题描述】:

我在 C++ 中有一个将双精度数组作为参数的方法。我从 Java 调用这个方法,需要传递一个双精度数组。 C++ 例程读取和修改数组的值,我需要 Java 中的这些更新值。我该怎么做?

以 C++ 例程为例:

void myMethod( double *values, int size ) {
    for ( int i=0; i < size; i++ ) {
        values[i] = 2*values[i];
    }
}

还有 Java 代码:

double[] values = { 1.3, 1.1 };
myMethod(values,values.length);
System.out.println(values[0]); // prints 2.6

我猜对 myMethod 的调用不能像上面的调用一样......或者可以吗?以及在 Swig 中完成这项工作所必需的。如果我无法像上面那样进行调用,如何将我的值传递给 C++ 代码?

【问题讨论】:

  • 是的,非常感谢安迪!您理解我的问题并给出了非常恰当的答案......我仍在寻找更多答案。我对大多数人的行为特别感兴趣,因为这种情况必须一直出现。大多数人使用 Swig 2 吗?大多数人都编写自己的类型图吗?对我来说,这两个听起来都很极端。
  • 如果我必须手动将数组复制到 C++ 中,那很好。如果我可以在 C++ 中分配一个数组并且必须使用特殊方法来访问 Java 中的值,那很好。大多数人在这种情况下会怎么做?
  • 上述方法需要在数组的每个项目上设置 setItem (index, value)。我无法想象没有更好的方法,尽管经过数小时的搜索我找不到它。有什么线索吗?

标签: java c++ swig


【解决方案1】:

使用 carrays.i!

Swig docs on carrays

%include carrays.i
%array_functions( double, double_array )

这两行代码在我的模块中创建了以下代码:

 public static SWIGTYPE_p_double new_double_array(int nelements) {
    long cPtr = SimulatorModuleJNI.new_double_array(nelements);
    return (cPtr == 0) ? null : new SWIGTYPE_p_double(cPtr, false);
  }

  public static void delete_double_array(SWIGTYPE_p_double ary) {
    SimulatorModuleJNI.delete_double_array(SWIGTYPE_p_double.getCPtr(ary));
  }

  public static double double_array_getitem(SWIGTYPE_p_double ary, int index) {
    return SimulatorModuleJNI.double_array_getitem(SWIGTYPE_p_double.getCPtr(ary), index);
  }

  public static void double_array_setitem(SWIGTYPE_p_double ary, int index, double value) {
    SimulatorModuleJNI.double_array_setitem(SWIGTYPE_p_double.getCPtr(ary), index, value);
  }

这允许我在 Java 中使用 C 数组...这解决了我的需求,并且是解决我的问题的最佳解决方案。谢谢大家的回答!

【讨论】:

  • 感谢您发布更简单的方法。我认为您应该接受自己的答案。 carray 的 SWIG 2.0 链接位于 swig.org/Doc2.0/SWIGDocumentation.html#Library_carrays
  • 这是最快的方法吗?我假设您需要使用 Java 数组中的元素数调用 SWIGTYPE_p_double,然后将每个项目复制到新数组,然后在 C++ 中对新数组执行处理,然后将每个项目复制回 Java 数组。有没有办法直接访问内存并在两种语言之间传递一个指针?还是由于 Java 和 Cxx 之间内存管理的差异,这些额外的复制操作是唯一的方法?
【解决方案2】:

SWIG typemaps 应该允许这样做。 SWIG 2.0 文档显示了这个example in Python

使用 Java,您可以在 SWIG 类型映射中使用 JNI 代码。 JNI 提供了 Get/ReleaseArrayElements 方法。我猜你可以在typemap(in) 中获得一个原生数组,然后在typemap(argout) 中释放它。

另一种方法是使用 std_vector.i 中现有的 SWIG 类型映射将您的数组复制到 std::vector 中。

【讨论】:

  • 这是一个很好的答案!谢谢!我可以使用这个解决方案。但是第一部分(编写我自己的类型图)很复杂,第二部分需要 Swig 2。目前我相信必须有一个更简单的解决方案......而且我不介意编写一些代码将数组复制到 C 中。我将更新我的问题...请参阅顶部的更新。
【解决方案3】:

假设你不能按照 org.life.java 的建议去做......

您可以查看IPC's 和文件。

您可以做的另一件事是通过将包含 C++ 代码的 exe 路径和数组作为参数传递给它来创建一个进程。 [Runtime.exec(java.lang.String, java.lang.String[])][2] 应该可以做到这一点。

[2]:http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Runtime.html#exec(java.lang.String,java.lang.String[])

【讨论】:

    【解决方案4】:

    如果只是那个单一的方法,重写它。如果您需要移植一个(大得多的)更大的 C++ 代码库,请使用JNI(或更简单的JNA)。这增加了相当多的代码开销,但它是可行的。

    【讨论】:

    • 嗯...这正是我正在做的...使用 JNI,因为它是一个大型代码库。所以我选择使用 Swig 来创建 JNI 包装器...因为 Swig 要简单得多
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-17
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多