Самое простое решение для этого вообще не предполагает написания JNI - фактически это метод 2 .Поэтому я использовал carrays.i для предоставления очень простого интерфейса, а затем написал небольшой кусочек Java, чтобы сделать представление public
более удобным и интуитивно понятным.Ключевым моментом является то, что вам нужно предоставить способ объединения знаний массива и его длины.Я собрал минимальный законченный пример, чтобы проиллюстрировать, что он возвращает массив Java, но он может одинаково работать для ArrayList
или любой коллекции, которая вам нравится.
Во-первых, файл заголовка со встроенной реализацией длякомпактность:
#ifndef TEST_H
#define TEST_H
struct Foo {
int v;
};
inline static struct Foo *getFoo() {
static struct Foo r[] = {{0},{1},{2}};
return r;
}
inline static unsigned short numFoo() {
return 3;
}
#endif
Затем он оборачивается:
%module test
%{
#include "test.h"
%}
%include <carrays.i>
%array_functions(struct Foo, foo_array);
%rename(getFooImpl) getFoo;
%javamethodmodifiers getFoo() "private";
%javamethodmodifiers numFoo() "private";
%include "test.h"
%pragma(java) modulecode=%{
public static Foo[] getFoo() {
final int num = numFoo();
Foo ret[] = new Foo[num];
Foo result = getFooImpl();
for (int i = 0; i < num; ++i) {
ret[i] = foo_array_getitem(result, i);
}
return ret;
}
%}
Где мы переименуем getFoo()
из заголовочного файла и сделаем его и соответствующий numFoo()
private
детали реализации.
Используя эти две частные функции, мы можем затем написать вещественное число, public Foo[] getFoo()
, которое вызывает эти две функции, а затем копирует результаты в фактический массив известного размера.
Я проверил это с помощью:
public class main {
public static void main(String[] argv) {
System.loadLibrary("test");
Foo[] foos = test.getFoo();
System.out.println(foos[2].getV());
}
}
На мой взгляд, это решение чище, чем соответствующий пример на основе JNI - его проще писать и труднее вводить ошибки, что делает его более удобным в обслуживании.Любой программист на Java или C, который смотрит на это, может в значительной степени увидеть, что происходит.Вероятно, это не намного хуже с точки зрения производительности и, вероятно, не будет большой частью времени на каком-то критическом пути - если тесты покажут, что это проблема, тогда все равно легко пойти по пути JNI позже.
Для полноты аспекта "make it private
" вы также можете сделать что-то вроде:
%javamethodmodifiers foo_array_getitem "private";
%ignore foo_array_setitem;
%ignore delete_foo_array;
%ignore new_foo_array;
%include <carrays.i>
%array_functions(struct Foo, foo_array);
Чтобы скрыть все функции, которые генерируются макросом %array_functions
.