如何使用Swig从Java传递数组到C++?

10

我有一个C++方法,它需要一个double数组作为参数。我从Java中调用此方法并需要传递一个double数组。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吗?大多数人编写自己的类型映射吗?对我来说,这两者都听起来像是极端情况。 - Jason
如果我需要手动将数组复制到C++中,那也没关系。如果我可以在C++中分配一个数组,并且必须使用Java中的特殊方法来访问值,那也没关系。在这种情况下,大多数人会怎么做? - Jason
上述方法需要在数组的每个项目上使用setItem(index,value)。 虽然我找了几个小时,但我无法想象没有更好的方法。有什么线索吗? - user809076
4个回答

8

使用carrays.i!

请查看Swig关于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数组......这解决了我的需求,是我问题的最佳解决方案。感谢大家的回答!


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

1

SWIG typemaps 应该允许这样做。 SWIG 2.0 文档中展示了 Python 的示例

对于 Java,您可以在 SWIG typemap 中使用 JNI 代码。JNI 提供了 Get/ReleaseArrayElements 方法。我猜想您可以在 typemap(in) 中获取本地数组,然后在 typemap(argout) 中释放它。

另一种方法是将数组复制到 std::vector 中,使用现有的 SWIG typemap 在 std_vector.i 中。


这是个很好的答案!谢谢!我可能会使用这个解决方案。但第一部分(编写自己的类型映射)比较复杂,第二部分需要使用Swig 2。目前我相信必须存在一个更简单的解决方案...而且我也不介意编写一些代码将数组复制到C中。我打算更新我的问题...请查看顶部的更新。 - Jason

0

0

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


嗯...那正是我正在做的事情...使用JNI,因为它是一个庞大的代码库。所以我选择使用Swig来创建JNI包装器...因为Swig要简单得多。 - Jason

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接