使用Kotlin 调用jni函数返回复杂的数组类对象:
kotlin:
package com.example.facedetectordemo.entity
class FaceInfo {
var rect: Rect? = null
lateinit var landmarks: Array<Landmark?>
var confidence: Float = 0f
class Rect {
val x: Int = 0
val y: Int = 0
val width: Int = 0
val height: Int = 0
}
class Landmark {
val x: Int = 0
val y: Int = 0
}
}
Jni C++:
extern "C"
JNIEXPORT jobjectArray JNICALL
Java_com_example_facedetectordemo_MainActivity_getFaceInfoList(JNIEnv *env, jobject thiz) {
// TODO: implement getFaceInfoList()
jobjectArray infos = NULL; // jobjectArray 为指针类型
jclass faceInfo = NULL; // jclass 为指针类型
jclass faceRect = NULL;
jclass faceLandmark = NULL;
jfieldID rectID;
jfieldID landmarksID;
jfieldID confidenceID;
jsize len;
int i;
faceInfo = env->FindClass("com/example/facedetectordemo/entity/FaceInfo");
faceRect = env->FindClass("com/example/facedetectordemo/entity/FaceInfo$Rect");
faceLandmark = env->FindClass("com/example/facedetectordemo/entity/FaceInfo$Landmark");
len = 5;
infos = env->NewObjectArray(len, faceInfo, NULL);
rectID = env->GetFieldID(faceInfo, "rect", "Lcom/example/facedetectordemo/entity/FaceInfo$Rect;");
landmarksID = env->GetFieldID(faceInfo, "landmarks", "[Lcom/example/facedetectordemo/entity/FaceInfo$Landmark;");
confidenceID = env->GetFieldID(faceInfo, "confidence", "F");
jfieldID faceRectXID = env->GetFieldID(faceRect, "x", "I");
jfieldID faceRectYID = env->GetFieldID(faceRect, "y", "I");
jfieldID faceRectWidthID = env->GetFieldID(faceRect, "width", "I");
jfieldID faceRectHeightID = env->GetFieldID(faceRect, "height", "I");
jfieldID faceLandmarkXID = env->GetFieldID(faceLandmark, "x", "I");
jfieldID faceLandmarkYID = env->GetFieldID(faceLandmark, "y", "I");
for(i = 0; i < len; i++)
{
jobject faceObj = env->AllocObject(faceInfo);
jobject faceRectObj = env->AllocObject(faceRect);
env->SetIntField(faceRectObj, faceRectXID, (jint) 5);
env->SetIntField(faceRectObj, faceRectYID, (jint) 6);
env->SetIntField(faceRectObj, faceRectWidthID, (jint) 8);
env->SetIntField(faceRectObj, faceRectHeightID, (jint) 10);
env->SetObjectField(faceObj, rectID, faceRectObj);
jobjectArray faceLanmarks = env->NewObjectArray(len, faceLandmark, NULL);
for(int j=0; j< 5; j++) {
jobject landmarkObj = env->AllocObject(faceLandmark);
env->SetIntField(landmarkObj, faceLandmarkXID, (jint) 5);
env->SetIntField(landmarkObj, faceLandmarkYID, (jint) 6);
env->SetObjectArrayElement(faceLanmarks, j, landmarkObj);
}
env->SetObjectField(faceObj, landmarksID, faceLanmarks);
env->SetFloatField(faceObj, confidenceID, (jfloat) 0.8);
env->SetObjectArrayElement(infos, i, faceObj);
}
return infos;
}
MainActivity.kt:
package com.example.facedetectordemo
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import com.example.facedetectordemo.databinding.ActivityMainBinding
import com.example.facedetectordemo.entity.FaceInfo
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// Example of a call to a native method
binding.sampleText.text = stringFromJNI()
val infos = getFaceInfoList()
Log.d("zhouyong", "onCreate: size " + infos.size)
}
/**
* A native method that is implemented by the 'facedetectordemo' native library,
* which is packaged with this application.
*/
external fun stringFromJNI(): String
external fun getFaceInfoList(): Array<FaceInfo>
companion object {
// Used to load the 'facedetectordemo' library on application startup.
init {
System.loadLibrary("facedetectordemo")
}
}
}