JNI数据操作

本实例中包含:
- ByteArray的操作Java<->JNI双向操作
- Java的Object转C的struct以及struct转Java的Object
- ArrayList对象的操作
- Java 数组对象的解析
- malloc 需要free
- ByteArray需要release

//
// Created by liuhui on 2017/11/18.
//
#include <jni.h>
#include <math.h>
#include "Fp16Convert.h"

static jbyteArray normalizeFeatures2(JNIEnv *env, jbyte *feature_, int len);

uint64_t sTaskId = -1;
char *detectFeatureFromPicClazz = "com.xxx.xxx.xxx.model.DetectFaceFromPicture";
char *faceServiceNotificationClazz = "com.xxx.xxx.xxx.model.FaceServiceNotification";

//char* to jstring
int sto(JNIEnv *env, const char *pat) {
    return 1;
}

jstring charTojstring(JNIEnv *env, char *chars) {
    jclass strClass = env->FindClass("Ljava/lang/String;");
    jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
    jbyteArray bytes = env->NewByteArray(strlen(chars));
    env->SetByteArrayRegion(bytes, 0, strlen(chars), (jbyte *) chars);
    jstring encoding = env->NewStringUTF("utf-8");
    return (jstring) env->NewObject(strClass, ctorID, bytes, encoding);
}

__attribute__((section (".mytext"))) static void nativeFaceDtrDestroy(JNIEnv *env, jobject thiz) {
    //LOGW("facedtr_jni destroy");
    sTaskId = -1;

}

__attribute__((section (".mytext"))) static int
nativeFaceDtrGetModelLength(JNIEnv *env, jobject thiz,
                            jstring name) {
    if (name == NULL) {
        //LOGE("clazz can't be null");
        return -1;
    }
    char *clazzName = (char *) env->GetStringUTFChars(name, NULL);

    int result = -2;
    if (strlen(clazzName) == strlen(detectFeatureFromPicClazz) &&
        memcmp(clazzName, detectFeatureFromPicClazz, strlen(detectFeatureFromPicClazz)) == 0) {

        result = sizeof(xxx_xxx_mobile2movi_pic_bytes);
    } else if (strlen(clazzName) == strlen(faceServiceNotificationClazz) &&
               memcmp(clazzName, faceServiceNotificationClazz,
                      strlen(faceServiceNotificationClazz)) == 0) {
        result = sizeof(xx_xxx_movi2mobile_notification_t);
    }
    env->ReleaseStringChars(name, (const jchar *) clazzName);
    env->DeleteLocalRef(name);
    return result;

}

__attribute__((section (".mytext"))) static jbyteArray
nativeFaceDtrInitParamter(JNIEnv *env, jobject thiz, jobject paramter) {
    xxx_xxx_initialzation_paramter_t *initParamter = (xxx_xxx_initialzation_paramter_t *) malloc(
            sizeof(xxx.xxx_initialzation_paramter_t));
    jbyteArray jbyteArray1 = env->NewByteArray(sizeof(xxx.xxx_initialzation_paramter_t));
    //Getting class have two method :
    jclass jParamsCls = env->GetObjectClass(paramter);

    //parse taskId
    jfieldID taskIdTypeField = env->GetFieldID(jParamsCls, "taskId", "J");
    uint64_t taskId = env->GetLongField(paramter, taskIdTypeField);
    sTaskId = taskId;
    initParamter->taskId = taskId;
//    //LOGW("initParamter->taskId = %ld,sTaskId = %ld ", initParamter->taskId,sTaskId);
    //parse ServiceType
    jfieldID serviceTypeField = env->GetFieldID(jParamsCls, "serviceType", "I");
    uint16_t serviceType = env->GetIntField(paramter, serviceTypeField);
//    //LOGW("serviceType = %d ", serviceType);
    initParamter->serviceType = (service_type) serviceType;
    //parse multipleFaceDetectDelayTime
    jfieldID multipleFaceDetectDelayTimeField = env->GetFieldID(jParamsCls,
                                                                "multipleFaceDetectDelayTime", "I");
    uint16_t multipleFaceDetectDelayTime = env->GetIntField(paramter,
                                                            multipleFaceDetectDelayTimeField);
    initParamter->multipleFaceDetectDelayTime = multipleFaceDetectDelayTime;

    //解析Java Object对象
    jfieldID areaFiledId = env->GetFieldID(jParamsCls, "area",
                                           "Lcom/xxx/xxx/xxx/model/Area;");
    //it works
//    jfieldID areaFiledId = env->GetFieldID(jParamsCls,"area","com/xxx/glass3/sdk/facedtr/Area"); 
    jobject areaObj = env->GetObjectField(paramter, areaFiledId);
    jclass areaClass = env->FindClass("com/xxx/xxx/xxx/model/Area");
    jfieldID leftFiledId = env->GetFieldID(areaClass, "left", "I");
    jfieldID topFiledId = env->GetFieldID(areaClass, "top", "I");
    jfieldID rightFiledId = env->GetFieldID(areaClass, "right", "I");
    jfieldID bottomFiledId = env->GetFieldID(areaClass, "bottom", "I");
    uint16_t left = env->GetIntField(areaObj, leftFiledId);
    uint16_t top = env->GetIntField(areaObj, topFiledId);
    uint16_t right = env->GetIntField(areaObj, rightFiledId);
    uint16_t bottom = env->GetIntField(areaObj, bottomFiledId);
//    //LOGW("(left,top),(right,bottom)-> (%d,%d),(%d,%d)", left, top, right, bottom);
    area_t a;
    a.left = left;
    a.top = top;
    a.right = right;
    a.bottom = bottom;
    initParamter->area = a;

    //parse detect discrimatorn
    jfieldID detectDiscrimatornField = env->GetFieldID(jParamsCls, "detectDiscrimatorn",
                                                       "Lcom/xxx/xxx/xxx/model/DetectThreshold;");
    jobject detectDiscrimatornObj = env->GetObjectField(paramter, detectDiscrimatornField);
//    jclass detectDiscrimatornClz = env->FindClass("com/xxx/glass3/sdk/facedtr/DetectThreshold");
    jclass detectDiscrimatornClz = env->GetObjectClass(detectDiscrimatornObj);
    jfieldID minDetectWidthField = env->GetFieldID(detectDiscrimatornClz, "minDetectWidth", "I");
    jfieldID countOfFastField = env->GetFieldID(detectDiscrimatornClz, "countOfFast", "I");
    jfieldID yawField = env->GetFieldID(detectDiscrimatornClz, "yaw", "I");

    uint16_t minDetectWidth = env->GetIntField(detectDiscrimatornObj, minDetectWidthField);
    uint16_t countOfFast = env->GetIntField(detectDiscrimatornObj, countOfFastField);
    uint16_t yaw = env->GetIntField(detectDiscrimatornObj, yawField);
    detect_discrimator_t detect_discrimator1;
    detect_discrimator1.yaw = yaw;
    detect_discrimator1.minDetectWidth = minDetectWidth;
    detect_discrimator1.countOfFast = countOfFast;
    initParamter->detectDiscrimatorn = detect_discrimator1;
//    //LOGW("coutOfFast = %d, yaw = %d, minDetectWidthField = %d ", countOfFast, yaw, minDetectWidth);

    //parse detectResultType
    jfieldID detectResultTypeFiled = env->GetFieldID(jParamsCls, "detectResultType", "I");
    uint16_t detectResultType = env->GetIntField(paramter, detectResultTypeFiled);
    initParamter->detectResultType = (detect_result_type) detectResultType;
//    //LOGW("detectResultType = %d", detectResultType);

    //parse indicatorColorSize
    jfieldID indicatorColorSizeFiled = env->GetFieldID(jParamsCls, "indicatorColorSize", "I");
    uint16_t indicatorColorSize = env->GetIntField(paramter, indicatorColorSizeFiled);
    initParamter->indicatorColorSize = indicatorColorSize;
//    //LOGW("indicatorColorSize = %d", indicatorColorSize);

    //parse indicatorColors
    if (indicatorColorSize != 0) {
        jfieldID indicatorColorsField = env->GetFieldID(jParamsCls, "indicatorColors",
                                                        "[Lcom/xxx/xxx/xxx/model/IndicatorColor;");
        jobjectArray indicatorColorArrayObj = (jobjectArray) env->GetObjectField(paramter,
                                                                                 indicatorColorsField);
//        //LOGD("数组长度:%d", env->GetArrayLength(indicatorColorArrayObj));

        for (int i = 0; i < indicatorColorSize; i++) {
            jobject indicatorColorObj = env->GetObjectArrayElement(indicatorColorArrayObj, i);
            jclass indicatorClz = env->GetObjectClass(indicatorColorObj);
            jfieldID indicatorColorSizeFiled = env->GetFieldID(indicatorClz, "state", "I");
            uint16_t state = env->GetIntField(indicatorColorObj, indicatorColorSizeFiled);
            indicator_color_t indicatorColor;
            indicatorColor.state = (face_track_phase) state;

            jfieldID indicatorColorFiled = env->GetFieldID(indicatorClz, "color", "I");
            uint16_t color = env->GetIntField(indicatorColorObj, indicatorColorFiled);
            indicatorColor.color = color;
            initParamter->indicatorColors[i] = indicatorColor;
            env->DeleteLocalRef(indicatorClz);
            env->DeleteLocalRef(indicatorColorObj);
        }
        env->DeleteLocalRef(indicatorColorArrayObj);
//        //LOGW("状态对应颜色值结束了");
    }


    //parse Camera width and height
    jfieldID jfieldIDCameraWidth = env->GetFieldID(jParamsCls, "cameraPreviewWidth", "I");
    uint16_t cameraWidth = env->GetIntField(paramter, jfieldIDCameraWidth);
    initParamter->cameraPreviewWidth = cameraWidth;
    jfieldID jfieldIDCameraHeight = env->GetFieldID(jParamsCls, "cameraPreviewheight", "I");
    uint16_t cameraHeight = env->GetIntField(paramter, jfieldIDCameraHeight);
    initParamter->cameraPreviewHeight = cameraHeight;
//    //LOGW("paramter cameraWidth = %dpx,cameraHeight = %dpx", cameraWidth, cameraHeight);
    env->SetByteArrayRegion(jbyteArray1, 0, sizeof(xxx.xxx_initialzation_paramter_t),
                            (const jbyte *) initParamter);
    free(initParamter);
    initParamter = NULL;
    env->DeleteLocalRef(jParamsCls);
    env->DeleteLocalRef(areaObj);
    env->DeleteLocalRef(areaClass);
    env->DeleteLocalRef(detectDiscrimatornObj);
    env->DeleteLocalRef(detectDiscrimatornClz);
//    //LOGW("convert paramters to byte[] len:%d",env->GetArrayLength(jbyteArray1));
    return jbyteArray1;
}


__attribute__((section (".mytext"))) static void
nativeParseFaceNotificationCallback(JNIEnv *env, jobject thiz, jbyteArray array, jobject callback) {
//    jbyte *raw_msg = env->GetByteArrayElements(array, 0);
    jclass clazz = env->GetObjectClass(callback);
    jmethodID faceNotificationCallbackMethodId = env->GetMethodID(clazz,
                                                                  "onFaceNotificationCallback",
                                                                  "(Lcom/xxx/xxx/xxx/model/FaceServiceNotification;)V");
    jbyte *data = env->GetByteArrayElements(array, NULL);
    int arrayLength = env->GetArrayLength(array);

    jbyte *raw_msg = (jbyte *) malloc(arrayLength);

    if (data != NULL) {
        memcpy(raw_msg, data, arrayLength);
        env->ReleaseByteArrayElements(array, data, JNI_ABORT);
        env->DeleteLocalRef(array);
    }

    xxx.xxx_movi2mobile_notification_t *notification = (xxx_xxx_movi2mobile_notification_t *) raw_msg;
    if (sTaskId != notification->taskId) {
        //LOGE("两次TaskID不相同 sTaskID = %ld,last  taskId = %ld ", sTaskId, notification->taskId);
        if (notification->notificationType == 3) { //detect face from pic
            env->CallVoidMethod(callback, faceNotificationCallbackMethodId, NULL);
        }
        free(raw_msg);
        raw_msg = NULL;
        notification = NULL;
        env->DeleteLocalRef(clazz);
        return;
    }
    const uint8_t *src = notification->resultData;
    uint8_t *dest = (uint8_t *) malloc(FRAME_YUV_LEN);
    const int yLen = 1280 * 720;
    const int vLen = yLen / 4;

    memcpy(dest, notification->resultData, yLen);//Y data
    for (int i = 0; i < vLen; i++) {
        dest[yLen + 2 * i] = src[yLen + i];//V data
        dest[yLen + 2 * i + 1] = src[yLen + vLen + i];//U data
    }
    uint8_t *features = notification->features;
    int notificationType = notification->notificationType;
    if (LIKELY(clazz)) {
        //get hid method ID

//        //LOGE("faceNotificationCallbackMethodId");

        jclass faceServiceNotificationClazz = env->FindClass(
                "com/xxx/xxx.xxx/model/FaceServiceNotification");
//        //LOGE("faceServiceNotificationClazz");
        //new FaceServiceNotification
        if (LIKELY(faceServiceNotificationClazz)) {

            jmethodID hid_method_creator = env->GetMethodID(faceServiceNotificationClazz, "<init>",
                                                            "(I[BLjava/util/ArrayList;[B)V");
            //construct arealist
            jclass list_cls = env->FindClass("java/util/ArrayList");//获得ArrayList类引用
//            //LOGW("Get ArrayList class");

            jmethodID list_costruct = env->GetMethodID(list_cls, "<init>", "()V"); //获得得构造函数Id
            jobject areaArrayList = env->NewObject(list_cls, list_costruct); //创建一个Arraylist集合对象
//            //LOGW("create ArrayList instance areaArrayList");
            //或得Arraylist类中的 add()方法ID,其方法原型为: boolean add(Object object) ;
            jmethodID list_add = env->GetMethodID(list_cls, "add", "(Ljava/lang/Object;)Z");
            jclass areaClz = env->FindClass("com/xxx/xxx/xxx/model/Area");
            for (int i = 0; i < notification->areasize; ++i) {
                area_t area1 = notification->area[i];
                jmethodID area_method_creator = env->GetMethodID(areaClz, "<init>", "(IIII)V");
                jobject areaObj = env->NewObject(areaClz, area_method_creator, area1.left,
                                                 area1.top,
                                                 area1.right + area1.left,
                                                 area1.bottom + area1.top);
                //执行Arraylist类实例的add方法,添加一个Area对象
                env->CallBooleanMethod(areaArrayList, list_add, areaObj);
            }
            env->DeleteLocalRef(list_cls);
            env->DeleteLocalRef(areaClz);


            jbyteArray notificationData = env->NewByteArray(FRAME_YUV_LEN);
            env->SetByteArrayRegion(notificationData, 0, FRAME_YUV_LEN, (const jbyte *) dest);

//            jbyteArray featureData = env->NewByteArray(FEATURES_LEN);
//            env->SetByteArrayRegion(featureData, 0, FEATURES_LEN, (const jbyte *) features);
            //归一化后的数据
            jbyteArray featureData = normalizeFeatures2(env, (jbyte *) features, FEATURES_LEN);

            jobject hidInfoObj = env->NewObject(faceServiceNotificationClazz, hid_method_creator,
                                                notificationType, notificationData,
                                                areaArrayList, featureData);
            env->CallVoidMethod(callback, faceNotificationCallbackMethodId, hidInfoObj);
            env->DeleteLocalRef(notificationData);
            env->DeleteLocalRef(areaArrayList);
            env->DeleteLocalRef(featureData);
            env->DeleteLocalRef(hidInfoObj);
        }
        env->DeleteLocalRef(faceServiceNotificationClazz);
    }
    env->DeleteLocalRef(clazz);
    notification = NULL;
    if (raw_msg != NULL) {
        free(raw_msg);
        raw_msg = NULL;
    }
    if (LIKELY(dest)) {
        free(dest);
        dest = NULL;
    }
    env->DeleteLocalRef(array);
    src = NULL;
    env->DeleteLocalRef(callback);
}


__attribute__((section (".mytext"))) static jobject
nativeParseFaceServiceNotification(JNIEnv *env, jobject thiz, jbyteArray array) {
    //LOGW("nativeParseFaceServiceNotification");
    jbyte *data = env->GetByteArrayElements(array, NULL);
    int arrayLength = env->GetArrayLength(array);
    jbyte *raw_msg = (jbyte *) malloc(arrayLength);
    if (data != NULL) {
        memcpy(raw_msg, data, arrayLength);
        env->ReleaseByteArrayElements(array, data, JNI_ABORT);
        env->DeleteLocalRef(array);
    }

    jobject faceServerNotificationObj = NULL;
    xxx.xxx_movi2mobile_notification_t *notification = (xxx.xxx_movi2mobile_notification_t *) raw_msg;
    if (sTaskId != notification->taskId) {
        //LOGE("different taskID taskID1 = %ld,last  taskId2 = %ld ", sTaskId, notification->taskId);
        free(raw_msg);
        raw_msg = NULL;
        notification = NULL;
        return faceServerNotificationObj;
    }
    const uint8_t *src = notification->resultData;
    uint8_t *dest = (uint8_t *) malloc(FRAME_YUV_LEN);
    const int yLen = 1280 * 720;
    const int vLen = yLen / 4;

    memcpy(dest, notification->resultData, yLen);//Y data
    for (int i = 0; i < vLen; i++) {
        dest[yLen + 2 * i] = src[yLen + i];//V data
        dest[yLen + 2 * i + 1] = src[yLen + vLen + i];//U data
    }
    uint8_t *features = notification->features;
    int notificationType = notification->notificationType;
    jclass faceServiceNotificationClazz = env->FindClass(
            "com/xxx/xxx.xxx/model/FaceServiceNotification");
    //new FaceServiceNotification

    jmethodID hid_method_creator = env->GetMethodID(faceServiceNotificationClazz, "<init>",
                                                    "(I[BLjava/util/ArrayList;[B)V");
    //construct arealist
    jclass list_cls = env->FindClass("java/util/ArrayList");//获得ArrayList类引用
//            //LOGW("Get ArrayList class");

    jmethodID list_costruct = env->GetMethodID(list_cls, "<init>", "()V"); //获得得构造函数Id
    jobject areaArrayList = env->NewObject(list_cls, list_costruct); //创建一个Arraylist集合对象
//            //LOGW("create ArrayList instance areaArrayList");
    //或得Arraylist类中的 add()方法ID,其方法原型为: boolean add(Object object) ;
    jmethodID list_add = env->GetMethodID(list_cls, "add", "(Ljava/lang/Object;)Z");
    jclass areaClz = env->FindClass("com/xxx/xxx.xxx/model/Area");
    for (int i = 0; i < notification->areasize; ++i) {
        area_t area1 = notification->area[i];
        jmethodID area_method_creator = env->GetMethodID(areaClz, "<init>", "(IIII)V");
        jobject areaObj = env->NewObject(areaClz, area_method_creator, area1.left,
                                         area1.top,
                                         area1.right + area1.left,
                                         area1.bottom + area1.top);
        //执行Arraylist类实例的add方法,添加一个Area对象
        env->CallBooleanMethod(areaArrayList, list_add, areaObj);
    }
    env->DeleteLocalRef(list_cls);
    env->DeleteLocalRef(areaClz);


    jbyteArray notificationData = env->NewByteArray(FRAME_YUV_LEN);
    env->SetByteArrayRegion(notificationData, 0, FRAME_YUV_LEN, (const jbyte *) dest);

//            jbyteArray featureData = env->NewByteArray(FEATURES_LEN);
//            env->SetByteArrayRegion(featureData, 0, FEATURES_LEN, (const jbyte *) features);
    //归一化后的数据
    jbyteArray featureData = normalizeFeatures2(env, (jbyte *) features, FEATURES_LEN);

    faceServerNotificationObj = env->NewObject(faceServiceNotificationClazz, hid_method_creator,
                                               notificationType, notificationData,
                                               areaArrayList, featureData);
    env->DeleteLocalRef(notificationData);
    env->DeleteLocalRef(areaArrayList);
    env->DeleteLocalRef(featureData);
    env->DeleteLocalRef(faceServiceNotificationClazz);
    notification = NULL;
    if (raw_msg != NULL) {
        free(raw_msg);
        raw_msg = NULL;
    }
    if (LIKELY(dest)) {
        free(dest);
        dest = NULL;
    }
    env->DeleteLocalRef(array);
    src = NULL;
    return faceServerNotificationObj;
}

__attribute__((section (".mytext"))) static jbyteArray nativeGetFace(JNIEnv *env, jobject thiz,
                                                                     jint dataType, jint size,
                                                                     jint width, jint height,
                                                                     jbyteArray bytes_) {
//    //LOGW("facedtr_jni nativeGetFace");

    xxx.xxx_mobile2movi_pic_bytes_t *mobile2moviPicBytes = (xxx_xxx_mobile2movi_pic_bytes_t *) malloc(
            sizeof(xxx.xxx_mobile2movi_pic_bytes));
    mobile2moviPicBytes->dataType = dataType;
    mobile2moviPicBytes->size = size;
    mobile2moviPicBytes->pic_width = width;
    mobile2moviPicBytes->pic_height = height;
    jint len = 0;
    if (bytes_ != NULL) {
        len = env->GetArrayLength(bytes_);
    }
    jbyteArray jbyteArray1 = env->NewByteArray(sizeof(xxx.xxx_mobile2movi_pic_bytes));
    if (len > 0) {
        jboolean isCopy;
        jbyte *bytes = env->GetByteArrayElements(bytes_, &isCopy);
        memcpy(mobile2moviPicBytes->bytes, bytes, len);
    }
    env->SetByteArrayRegion(jbyteArray1, 0, sizeof(xxx.xxx_mobile2movi_pic_bytes),
                            (const jbyte *) mobile2moviPicBytes);
    free(mobile2moviPicBytes);

    mobile2moviPicBytes = NULL;
//    //LOGW("%d,%d",env->GetArrayLength(jbyteArray1), sizeof(*mobile2moviPicBytes));

    return jbyteArray1;
}


__attribute__((section (".mytext"))) static jbyteArray
normalizeFeatures(JNIEnv *env, jobject thiz, jbyteArray feature_) {
    jbyte *feature = env->GetByteArrayElements(feature_, NULL);
    jbyteArray result = normalizeFeatures2(env, feature, 1024);
    if (feature != NULL) {
        env->ReleaseByteArrayElements(feature_, feature, JNI_ABORT);
        env->DeleteLocalRef(feature_);
        feature = NULL;
    }
    return result;
}


static jbyteArray normalizeFeatures2(JNIEnv *env, jbyte *feature, int len) {
    //sto(env, KEY2);
    float norm_feature[256];
    float temp[512];
    for (int i = 0; i < 512; i++) {
        temp[i] = f16Tof32(*(unsigned int *) ((unsigned short *) feature + i));
    }

    const float *ptr = temp;
    float sum = 0.0;
    for (int i = 0; i < 512; i++) {
        float num = *ptr++;
        sum += num * num;
    }
    sum = sqrtf(sum);

    ptr = temp;
    float sum2 = 0;

    for (int i = 0; i < 512; i++) {
        temp[i] = *ptr++ / sum;
    }
    for (int i = 0; i < 256; i++) {
        unsigned int x1 = f32Tof16(temp[i * 2]);
        unsigned int x2 = f32Tof16(temp[i * 2 + 1]);
        unsigned int x = x2 << 16 | x1;
        norm_feature[i] = *(float *) &x;
    }

    jbyteArray result = env->NewByteArray(1024);
    env->SetByteArrayRegion(result, 0, 1024, (jbyte *) norm_feature);
    return result;
}


//**********************************************************************
//
//**********************************************************************
jint registerNativeMethods(JNIEnv *env, const char *class_name, JNINativeMethod *methods,
                           int num_methods) {
    int result = 0;

    jclass clazz = env->FindClass(class_name);
    if (LIKELY(clazz)) {
        int result = env->RegisterNatives(clazz, methods, num_methods);
        if (UNLIKELY(result < 0)) {
            //LOGD("registerNativeMethods failed(class=%s)", class_name);
        }
    } else {
        //LOGD("registerNativeMethods: class'%s' not found", class_name);
    }
    return result;
}

static JNINativeMethod methods[] = {
        {"nativeFaceDtrDestroy",                "()V",                                                                              (void *) nativeFaceDtrDestroy},
        {"nativeFaceDtrInitParamter",           "(Lcom/xxx/xxx/xxx/model/FaceInitParamter;)[B",                               (void *) nativeFaceDtrInitParamter},
        {"nativeGetFace",                       "(IIII[B)[B",                                                                       (void *) nativeGetFace},
        {"normalizeFeatures",                   "([B)[B",                                                                           (void *) normalizeFeatures},
        {"nativeParseFaceNotificationCallback", "([BLcom/xxx/xxx/xxx/glxss/security/listener/IOnFaceNotificationCallback;)V", (void *) nativeParseFaceNotificationCallback},
        {"nativeParseFaceServiceNotification",  "([B)Lcom/xxx/xxx/xxx/model/FaceServiceNotification;",                        (void *) nativeParseFaceServiceNotification},
        {"nativeFaceDtrGetModelLength",         "(Ljava/lang/String;)I",                                                            (void *) nativeFaceDtrGetModelLength},


};

int register_libFaceDtr(JNIEnv *env) {
    //LOGI("register_libfacedtr:");
    if (registerNativeMethods(env,
                              "com/xxx/xxx/xxx/glxss/FaceDtr",
                              methods, NUM_ARRAY_ELEMENTS(methods)) < 0) {
        return -1;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值