Я создал тестовый пример, который отражает то, что вы пытаетесь сделать (я думаю):
#include <stdlib.h>
enum thing {
ONE=1,
TWO=2,
THREE=3
};
static signed char *get_data(enum thing t, size_t *len) {
*len = (size_t)t;
signed char *ret = malloc(sizeof(signed char) * (*len));
for (size_t i = 0; i < *len; ++i) {
ret[i] = i;
}
return ret;
}
Для переноса get_data()
Я использовал следующий интерфейс:
%module test
%{
#include "test.h"
%}
%typemap(jni) signed char *get_data "jbyteArray"
%typemap(jtype) signed char *get_data "byte[]"
%typemap(jstype) signed char *get_data "byte[]"
%typemap(javaout) signed char *get_data {
return $jnicall;
}
%typemap(in,numinputs=0,noblock=1) size_t *len {
size_t length=0;
$1 = &length;
}
%typemap(out) signed char *get_data {
$result = JCALL1(NewByteArray, jenv, length);
JCALL4(SetByteArrayRegion, jenv, $result, 0, length, $1);
}
%include "test.h"
По сути, это устанавливает тип возвращаемого значения из функции get_data
как массив Java прямо из кода JNI на всем протяжении прокси SWIG. Как только это будет сделано, он устанавливает временный size_t
с именем length
, который будет использоваться для вызова реальной функции C и сохранения результата. (Я не видел noblock
до того, как увидел этот ответ на другой вопрос , он говорит SWIG не делать аргумент карты типов независимым и, как таковой, означает, что для параметра может быть только один size_t *len
если вам интересно, посмотрите, что она делает с генерируемым кодом-оберткой.
Как только это будет установлено, остается только выделить массив с помощью вызова JNI и скопировать в него некоторые значения.
Я проверял это с:
public class run {
public static void main(String[] argv) {
System.loadLibrary("test");
byte[] test1 = test.get_data(thing.ONE);
System.out.println(test1.length);
System.out.println(test1 + ": " + test1[0]);
byte[] test2 = test.get_data(thing.TWO);
System.out.println(test2.length);
System.out.println(test2 + ": " + test2[0] + ", " + test2[1]);
byte[] test3 = test.get_data(thing.THREE);
System.out.println(test3.length);
System.out.println(test3 + ": " + test3[0] + ", " + test3[1] + ", " + test3[2]);
}
}
Который затем дал:
1
[B@525483cd: 0
2
[B@2a9931f5: 0, 1
3
[B@2f9ee1ac: 0, 1, 2
Я немного обманул, сделав мой signed char
. Если вы хотите сделать его без знака, вы должны либо использовать приведение (в лучшем случае остерегайтесь потери знака), либо short
/ int
с соответствующим преобразованием.
Будьте осторожны с владением памятью в вашем реальном коде.