你在這裏用array_functions
所做的是正確和可用的,但它的重點是直接包裝C++代碼,它不會使用底層Java數組。你可以像使用它:
SWIGTYPE_p_long_long array = MyLib.new_long_long_array(100); // new array with 100 elements.
for (int i = 0; i < 100; ++i) {
long_long_array_setitem(array, i, i);
}
new Test().SelectValues(array);
其中陣列只是一個代理一個「真正的」 C++的內存塊,你可以在Java端的讀/寫,並傳遞給包裹功能。
我從你的問題猜測你有興趣讓這種感覺在Java方面更「自然」。 SWIG還提供了array_class
,它類似地包裝一個數組,但是作爲一個適當的對象而不是靜態函數的集合。例如,如果您更改爲使用array_class(long long, LongLongArray)
,而不是你的array_functions
接口文件,你可以這樣做:
LongLongArray array = new LongLongArray(100);
for (int i = 0; i < 100; ++i) {
array.setitem(i,i);
}
new Test().SelectValues(array.cast());
實際上,你可以做,如果你想痛飲做的比這更多的與幾個typemaps。你的示例類沒有在SelectValues
中佔用長度,所以我假設你終止了數組,儘管你可以通過一些簡單的改變來傳遞長度。
(爲方便起見,我%inline
ð類,以減少文件的數量,並增加了測試的虛擬實現的話)
%module MyLib
%{
#include <iostream>
%}
%typemap(jtype) long long values[] "long[]"
%typemap(jstype) long long values[] "long[]"
%typemap(javain) long long values[] "$javainput"
%typemap(jni) long long values[] "jlongArray"
%typemap(in) long long values[] {
jboolean isCopy;
$1 = JCALL2(GetLongArrayElements, jenv, $input, &isCopy);
}
%inline %{
class Test
{
public:
void SelectValues(long long values[]) {
while (*values) {
std::cout << *values++ << "\n";
}
}
};
%}
在這裏,我們說,無論是代理類SWIG生成和JNI類它生成將與long[]
,即一個Java數組一起工作。我們不需要在Java代理到Java JNI轉換中做任何事情,因此javain
typemap只是一個直通過程。在JNI的C++端,這是我們在另一個typemap中指定的jlongArray
。
然後,我們需要一個in
類型表安排在C++側jlongArray轉換爲long long[]
- 有一個單一的JNI調用了這一點,我們不關心,如果它是從我們最終的JVM副本或實際內存使用。(你可能不在乎,如果你想修改的結果,並使其可見回場內的Java爲例)
我測試了:
public class run {
public static void main(String[] argv) {
System.loadLibrary("mylib");
long arr[] = {100,99,1,0}; // Terminate with 0!
new Test().SelectValues(arr);
}
}
這的確完全按照你的希望。
您在JNI方面看到的'jlong'是SWIG如何包裝所有不是原始類型的東西。 – Flexo