我想从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数组,它具有w
和h
作为输出函数的两个大小参数。
这比您的示例案例和针对C而不是C++的示例要简单一些(但是JCALLx宏的优点在于它们适用于任何一种语言)。 (注意:如果您使用的是C++,请根据需要使用std::array
或std::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);
}
}