当您需要/拥有作为本机java数组的数据时,carrays.i与arrays\u java.i的SWIG效率

当您需要/拥有作为本机java数组的数据时,carrays.i与arrays\u java.i的SWIG效率,java,swig,Java,Swig,我很好奇swig中关于swig/java中处理数组的两种基本方法的效率的说法。特别是,我想知道如果您最终需要向本机java数组进行复制或从本机java数组进行复制,那么carrays.I方法是否真的更有效?例如,假设我要调用一个C func void populate(int x[]),然后我需要将结果传递给一个采用本机Java int[]的Java func。要以carrays的方式进行,我需要: %include "carrays.i" %array_class(int, intArray)

我很好奇swig中关于swig/java中处理数组的两种基本方法的效率的说法。特别是,我想知道如果您最终需要向本机java数组进行复制或从本机java数组进行复制,那么carrays.I方法是否真的更有效?例如,假设我要调用一个C func void populate(int x[]),然后我需要将结果传递给一个采用本机Java int[]的Java func。要以carrays的方式进行,我需要:

%include "carrays.i"
%array_class(int, intArray);

intArray array = new intArray(10000000);
populate(array);
然后复制到本机java阵列:

int[] nativeArray = new int[10000000];
for(int i = 0; i < 10000000; ++i)
{
    nativeArray[i] = array.getitem(i);
} 
这真的比你想象的更有效率吗

%include "arrays_java.i"
int[] nativeArray = new int[10000000];
populate(nativeArray);
f(nativeArray);

因为在前一种情况下,您无论如何都必须进行复制?

假设您使用的是carrays。那么,您也不是在Java数组之间来回复制-您希望使用carrays。我在任何地方键入,而不是那样

仍然有两种类型的开销需要度量——JNI调用会招致某种惩罚,而复制另一种惩罚。使用carray.i,后者被保持在较低的水平,以获得您正确识别的更多JNI调用的价格。另外,对
GetArrayElements
的调用也可能会根据JVM引入一个副本

然而,可能令人惊讶的是,arrays_java.i的实现产生的副本比您预期的要多,例如,类型映射使用的SWIG_JavaArrayIn函数包含以下内容:

传递指向从VM获得的Java数组的指针(该数组可能是副本,也可能不是副本,您可以使用可选的第三个参数检查
GetIntArrayElements
,该参数是一个布尔值,指示JVM是否在进程中创建了副本)

这些类型映射以“原样”的形式传递Java数组,然后从JVM获取一个指针以在C函数中使用。如果函数成功,则调用
releaseintarayelements
,第三个参数为0-这确保Java中的任何修改也可见。如果调用不成功,则将使用
JNI\u ABORT
调用该函数,在返回的指针是副本的情况下,该函数不会做出任何可见的更改

我们可以称之为:

public class run {
  public static void main(String[] argv) {
    System.loadLibrary("test");
    int[] arr = new int[100000];
    test.populate(arr);
    // Only print 40 to avoid spamming my screen!
    for (int i = 0; i < 40; ++i) {
      System.out.println(arr[i]);
    }
  }
}
公共类运行{
公共静态void main(字符串[]argv){
系统加载库(“测试”);
int[]arr=新int[100000];
测试。填充(arr);
//只打印40,以避免垃圾邮件我的屏幕!
对于(int i=0;i<40;++i){
系统输出打印项数(arr[i]);
}
}
}

它可能有0个副本,但只能在Java中的类型与C中的相应类型完全匹配的情况下使用。

Hmm,在arrays_Java.i版本中可能有2个隐式副本,这仍然会降低效率?谢谢。我最关心的是将字节数组传递到C/C++中,它看起来像各种类型的char*字节类型映射。我类似于上面为int[]编写的高效类型映射。
  for (i=0; i<sz; i++)
    JAVA_TYPEMAP_ARRAY_ELEMENT_ASSIGN(CTYPE)
  for (i=0; i<sz; i++)
    arr[i] = (JNITYPE)result[i];
%module test

%typemap(jtype) int arr[ANY] "int[]"
%typemap(jstype) int arr[ANY] "int[]"
%typemap(jni) int arr[ANY] "jintArray"
%typemap(javain) int arr[ANY] "$javainput"
%typemap(in) int arr[ANY] {
  // check the size is compatible here also
  $1 = JCALL2(GetIntArrayElements, jenv, $input, 0);
}
%typemap(freearg) int arr[ANY] {
  if ($1) {
    JCALL3(ReleaseIntArrayElements, jenv, $input, $1, JNI_ABORT);
  }
}
%typemap(argout) int arr[ANY] {
  JCALL3(ReleaseIntArrayElements, jenv, $input, $1, 0);
  $1 = NULL;
}

%inline %{
void populate(int arr[100000]) {
  for (unsigned i = 0; i < 100000; ++i) {
    arr[i] = -i;
  }
}
%}
public class run {
  public static void main(String[] argv) {
    System.loadLibrary("test");
    int[] arr = new int[100000];
    test.populate(arr);
    // Only print 40 to avoid spamming my screen!
    for (int i = 0; i < 40; ++i) {
      System.out.println(arr[i]);
    }
  }
}