轉自: https://blog.csdn.net/zhangchao012/article/details/8546896
jni返回結構體數組.這個卡了我兩天.好鬱悶.從網上找了好多的辦法都不成功. 可能是人品問題,呵呵呵
好在現在搞定了.把源碼貼出來讓大家也看看,希望能幫到那些和我人品不好的人嘿嘿..
其實回想起來.挺簡單的. 返回結構體數組有如下步驟.
/*
* 返回一個結構體數組步驟
* 1.通過FindClass找到要返回的android中定義的class.
* 2.通過NewObjectArray創建一個要返回的結構體數組.
* 3.通過GetMethodID得到你要返回的class的默認構造方法
* 4.通過GetFieldID得到定義的class裏面所有的成員
* 5.通過NewObject創建一個對應的class對象
* 6.通過SetObjectField爲5創建的class對象賦值(如果字段爲int,那麼就用SetIntField這個方法)
* 7.通過SetObjectArrayElement把創建的class對象放到創建的objectArray裏面去
* 8.返回這個objectArray對象.
* 9.完成. 就這麼簡單.
* */
是不是簡單啊. 嘿嘿嘿嘿.
好.現在看是放源碼.
android 代碼.
這個代碼是activity 代碼
package com.example.jnitest2;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MX2 changeJni = new MX2();
changeJni.displayParms("Hello World!", 100, true);
int ret = changeJni.add(12, 20);
Log.e("logZ", "相加結果爲:"+ret);
boolean[] blList = new boolean[] { true, false, true };
changeJni.setArray(blList);
String[] strList = changeJni.getStringArray();
for (int i = 0; i < strList.length; i++)
{
Log.e("logZ", "第"+i+"string爲:"+ strList[i]);
}
//返回一個結構
mx2Data data = changeJni.getStruct();
Log.e("logZ", "名稱爲"+data.name+"序列爲"+data.index);
//返回一個結構數組
mx2Data[] dataList = changeJni.getStructArray();
for (int i = 0; i < dataList.length; i++)
{
Log.e("logZ", "第"+i+"個:"+"名稱爲"+data.name+"序列爲"+data.index);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
這個是調用jni代碼
<code class="language-html">package com.example.jnitest2;
public class MX2 {
static {
System.loadLibrary("myjni");
}
public native void displayParms(String showText, int i, boolean bl);
// 返回兩個int相加
public native int add(int a, int b);
// 輸入一個數組
public native void setArray(boolean[] blList);
// 返回一個字符串數組
public native String[] getStringArray();
// 返回一個結構
public native mx2Data getStruct();
// 返回一個結構數組
public native mx2Data[] getStructArray();
}
</code>
這個是要返回的結構體(在java中好像叫類 嘿嘿)
package com.example.jnitest2;
public class mx2Data{
public String name;
public int index;
}
這裏還是放jni源碼
<code class="language-java">#include "jni.h"
#include <stdio.h>
#include <math.h>
#include <stdio.h>
#include "stdlib.h"
#include "string.h"
/*
作用爲:
傳入的參數爲:string, int, boolean
返回是處理後的s.
*/
JNIEXPORT void JNICALL jni_displayParms(JNIEnv *env, jobject obj, jstring s, jint i, jboolean b)
{
const char* szStr = (env)->GetStringUTFChars(s, 0 );
printf( "String = [%s]\n", szStr );
printf( "int = %d\n", i );
printf( "boolean = %s\n", (b==JNI_TRUE ? "true" : "false") );
(env)->ReleaseStringUTFChars(s, szStr );
}
/*
返回兩個整數相加.
*/
JNIEXPORT jint JNICALL jni_add(JNIEnv *env, jobject, jint a, jint b)
{
int rtn = (int) (a + b);
return (jint) rtn;
}
/*
處理一個bool數組.
*/
JNIEXPORT void JNICALL jni_setArray(JNIEnv *env, jobject, jbooleanArray ba)
{
jboolean* pba = (env)->GetBooleanArrayElements(ba, 0 );
jsize len = (env)->GetArrayLength(ba);
int i=0;
for( i=0; i < len; i+=2 )
{
pba[i] = JNI_FALSE;
printf( "boolean = %s\n", (pba[i]==JNI_TRUE ? "true" : "false") );
}
(env)->ReleaseBooleanArrayElements(ba, pba, 0 );
}
/*
返回一個string數組.
*/
JNIEXPORT jobjectArray JNICALL jni_getStringArray(JNIEnv *env, jobject)
{
jstring str;
jobjectArray args = 0;
jsize len = 5;
const char* sa[] = { "Hello,", "world!", "mx2", "is", "good" };
int i = 0;
args = (env)->NewObjectArray(len, (env)->FindClass("java/lang/String"), 0);
for (i = 0; i < len; i++)
{
str = (env)->NewStringUTF(sa[i]);
(env)->SetObjectArrayElement(args, i, str);
}
return args;
}
/*
返回一個java object對象.
*/
JNIEXPORT jobject JNICALL jni_getStruct(JNIEnv *env, jobject obj)
{
//獲取Java中的mx2Data類
jclass objectClass = (env)->FindClass("com/example/jnitest2/mx2Data");
//得到這個類的構造方法id. //得到類的默認構造方法的id.都這樣寫.
jmethodID consID = (env)->GetMethodID(objectClass, "<init>", "()V");
//獲取類中每一個變量的定義
//name
jfieldID str = (env)->GetFieldID(objectClass, "name", "Ljava/lang/String;");
//index
jfieldID idex = (env)->GetFieldID(objectClass, "index", "I");
//創建一個jobject對象.
jobject myReturn = (env)->NewObject(objectClass, consID);
//給每一個實例的變量賦值
(env)->SetObjectField(myReturn, str, (env)->NewStringUTF("mei xiang 2"));
(env)->SetIntField(myReturn, idex, 10);
return myReturn;
}
/*
返回一個jobject數組. 這裏放回的是 mx2Data類的數組.
*/
JNIEXPORT jobjectArray JNICALL jni_getStructArray(JNIEnv *env, jobject _obj)
{
jobjectArray MXArray = NULL; // jobjectArray 爲指針類型
jclass clsMX = NULL; // jclass 爲指針類型
jobject obj;
jint len = 5; //設置這個數組的長度.
//知道要返回的class.
clsMX = env->FindClass("com/example/jnitest2/mx2Data");
//創建一個MXAray的數組對象.
MXArray = env->NewObjectArray(len, clsMX, NULL);
//獲取類中每一個變量的定義
//name
jfieldID str = (env)->GetFieldID(clsMX, "name", "Ljava/lang/String;");
//index
jfieldID idex = (env)->GetFieldID(clsMX, "index", "I");
//得到這個類的構造方法id. //得到類的默認構造方法的id.都這樣寫.
jmethodID consID = (env)->GetMethodID(clsMX, "<init>", "()V");
for (jint i = 0; i < len; i++)
{
obj = env->NewObject(clsMX, consID);
env->SetObjectField(obj, str, env->NewStringUTF("mx is mingxiang"));
env->SetIntField(obj, idex, (jint) i);
env->SetObjectArrayElement(MXArray, i, obj);
}
return MXArray;
}
/*
創建調用的方法數組.
{ "displayParms", "(Ljava/lang/String;IZ)V", (void*)jni_displayParms },
java裏面調用的方法 , (java調用時傳入的參數類型)返回的類型 , 對應的jni裏面的函數.
*/
static JNINativeMethod const gMethods[] =
{
{ "displayParms", "(Ljava/lang/String;IZ)V", (void*)jni_displayParms },
{ "add", "(II)I", (void*)jni_add },
{ "setArray", "([Z)V",(void*)jni_setArray },
{ "getStringArray", "()[Ljava/lang/String;",(void*) jni_getStringArray },
{ "getStruct", "()Lcom/example/jnitest2/mx2Data;",(void*) jni_getStruct },
{ "getStructArray", "()[Lcom/example/jnitest2/mx2Data;",(void*) jni_getStructArray },
};
/*
jni_Onload方法.照着寫就行了.
*/
jint JNI_OnLoad(JavaVM *jvm, void *reserved)
{
JNIEnv* env = NULL;
if (jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
return -1;
}
jclass clazz = (env)->FindClass("com/example/jnitest2/MX2"); //這裏是唯一的要注意的. 這裏的mx2是在java中引用jni類的類名.
(env)->RegisterNatives(clazz, gMethods, sizeof(gMethods) / sizeof(gMethods[0]));
return JNI_VERSION_1_4;
}
void JNI_OnUnload(JavaVM *jvm, void *reserved)
{
return;
}
</code>