我想从Java代码向C++代码发送一个多维数组(Java中的short[][],C++中的short int[][]),以处理一些计算,然后用Java代码获取该数组!

对于一维数组它工作正常。

example.i:

%module example

%{
#include <iostream>
#include "example.h"
%}

%typemap(jtype) short int values[] "short[]"
%typemap(jstype) short int[] "short[]"
%typemap(javain) short int values[] "$javainput"
%typemap(jni) short int values[] "jshortArray"
%typemap(in) short int values[] {
  jboolean isCopy;
  $1 = JCALL2(GetShortArrayElements, jenv, $input, &isCopy);
}

%typemap(in,numinputs=0,noblock=1) int *data_len {
   int temp_len;
   $1 = &temp_len;
}


%typemap(jstype) const short int *CPPtoJava "short[]"
%typemap(jtype) const short int *CPPtoJava "short[]"
%typemap(jni) const short int *CPPtoJava "jshortArray"

%typemap(javaout) const short int *CPPtoJava {
  return $jnicall;
}


%typemap(out) const short int *CPPtoJava {
  $result = JCALL1(NewShortArray, jenv, temp_len);
  JCALL4(SetShortArrayRegion, jenv, $result, 0, temp_len, $1);
}



%include "example.h"

example.h:
class Test
{
public:

    short int* data;
    size_t l;

    void JavaToCPP(short int values[], size_t len) {
        this->l = len;
        this->data = values;
    }

    const short int *CPPtoJava(int *data_len){
        *data_len = this->l ;
        return this->data;
    }

    void process(){
        for(int i = 0 ; i< this->l ; i++){
            this->data[i] = i;
        }
    }


};

MainRunner.java
public class MainRunner {
    public static void main(String[] argv) {
        System.load("/path/to/../libexample.so");

        short in[] = {0,0,0};
        System.out.println("\nInput : ");
        for (int i = 0; i < in.length; ++i) {
              System.out.print(in[i] + "\t");
        }


        Test t = new Test();
        t.JavaToCPP(in,(long)in.length);
        t.process();


        short[] out = t.CPPtoJava();
        System.out.println("\n\nOutput : ");
        for (int i = 0; i < out.length; ++i) {
              System.out.print(out[i] + "\t");
        }
      }
}

您知道如何在Swig中处理多维数组吗?

谢谢你的帮助 !

最佳答案

我创建了一个头文件来说明您可能要使用此头文件的情况。为了支持非正方形2D数组,它具有wh作为输出函数的两个大小参数。

这比您的示例案例和针对C而不是C++的示例要简单一些(但是JCALLx宏的优点在于它们适用于任何一种语言)。 (注意:如果您使用的是C++,请根据需要使用std::arraystd::vector而是免费获取所有包装)。

#include <stdlib.h>
#include <string.h>

short **CPPtoJava(size_t *w, size_t *h) {
  *w = 3;
  *h = 4;
  short **data = malloc(sizeof(short*) * *w);
  for (size_t i = 0; i < *w ; ++i) {
    data[i] = malloc(sizeof(short) * *h);
    for (size_t j = 0; j < *h; ++j) {
      data[i][j] = (1+i)*(1+j);
    }
  }
  return data;
}

void JavaToCPP(short **values, size_t w, size_t h) {
  for (size_t i = 0; i < w; ++i) {
    for (size_t j = 0; j < h; ++j) {
      printf("(%zu, %zu): %d\n", i, j, (int)values[i][j]);
    }
  }
}

有了这个,我们可以编写一些类型映射来封送Java中的数据。它们与一维情况没有太大不同,除了我们设置并构建了N个1D数组和1个数组。
%module test

%{
#include "test.h"
#include <assert.h>
%}

// For the outputs
%typemap(jni) short ** "jobjectArray"
%typemap(jstype) short ** "short[][]"
%typemap(jtype) short ** "short[][]"
%typemap(javaout) short ** {
  return $jnicall;
}
%typemap(in,numinputs=0) size_t *w %{
  size_t w=0;
  $1 = &w;
%}
%typemap(in,numinputs=0) size_t *h %{
  size_t h=0;
  $1 = &h;
%}
%typemap(out) short ** {
  $result = JCALL3(NewObjectArray, jenv, w, JCALL1(FindClass, jenv, "[S"), NULL);
  for (size_t i = 0; i < w; ++i) {
    jshortArray cur = JCALL1(NewShortArray, jenv, h);
    JCALL4(SetShortArrayRegion, jenv, cur, 0, h, $1[i]);
    JCALL3(SetObjectArrayElement, jenv, $result, i, cur);
  }
  free(result); // Since I called malloc this is needed
}


// For the inputs

%typemap(jni) (short **values, size_t w, size_t h) "jobjectArray"
%typemap(jstype) (short **values, size_t w, size_t h) "short[][]"
%typemap(jtype) (short **values, size_t w, size_t h) "short[][]"
%typemap(javain) (short **values, size_t w, size_t h) "$javainput"
%typemap(in,numinputs=1,noblock=1) (short **values, size_t w, size_t h) {
  $2 = JCALL1(GetArrayLength, jenv, $input);
  $1 = alloca(sizeof(short*) * $2); // Or maybe not on stack if you prefer?
  $3 = 0;
  if ($2 > 0) {
    jshortArray dim1 = JCALL2(GetObjectArrayElement, jenv, $input, 0);
    $3 = JCALL1(GetArrayLength, jenv, dim1);
  }

  for (size_t i = 0; i < $2; ++i) {
    jshortArray cur = JCALL2(GetObjectArrayElement, jenv, $input, i);
    assert((size_t)JCALL1(GetArrayLength, jenv, cur) == $3); // TODO: handle error
    $1[i] = JCALL2(GetShortArrayElements, jenv, cur, NULL);
  }
}
%typemap(freearg) (short **values, size_t w, size_t h) {
  for (size_t i = 0; i < $2; ++i) {
    jshortArray cur = JCALL2(GetObjectArrayElement, jenv, $input, i);
    JCALL3(ReleaseShortArrayElements, jenv, cur, $1[i], JNI_ABORT);
  }
}

%include "test.h"

有一个断言隐藏在其中以防止人们创建不规则形状的(即非矩形2D数组)

有了它,我们就可以运行:

import java.util.Arrays;

public class run {
  private static void print(short[][] arr) {
    for (int i = 0; i < arr.length; ++i) {
      System.out.println(Arrays.toString(arr[i]));
    }
  }

  public static void main(String[] argv) {
    System.loadLibrary("test");
    short[][] r1 = test.CPPtoJava();
    print(r1);
    test.JavaToCPP(r1);
  }
}

10-04 14:39