zoukankan      html  css  js  c++  java
  • jni相关

    封装 jni 的 java 层 Integer、Long 对象使用时必须用 new 对象的形式,防止修改 128>x x>-128 之间缓存的对象,一定要谨记

    配置

    在 eclipse 环境下开发 jni
    1. 导入 ndk Window->Preferences->Android->NDK,点击 Browse 引入 ndk 的目录
    2. 创 建 java 类 , 声 明 一 个 private native String CBBT_getVersionString();

    JNIEXPORT jstring JNICALL Java_com_raiing_ABBTSurface_getVersionString(JNIEnv *env,

    jobject obj)
    3. 使用 javah 生成 jni 头文件.

    3-a. run - external tools - external tools configuration - program - new lanch configuration 3-b. name:javah

    location:jdk 安装目录中的 javah.exe 所在目录javah.exe FilesJavajdk1.7.0_02injavah.exe

    working directory: ${workspace_loc}

    arguments: -v -classpath "${project_loc}/bin/classes" ${java_type_name}

    common - Display in favorites menu - 选中 External tools 中显示 javah。
    3-c. apply , close
    3-d. 点中 src- com.raiing - CTMProcess.java 文件

    3-e. run - external tools - javah 将生成 jni 的头文件在 jni 目录下。按 F5 刷新 project explorer 的 jni 目录。

    4. 添加 Android.mk 和 Application.mk 文件到 jni 目录。 android.mk 内容:

    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog

    LOCAL_MODULE := child 自己起的库名字

    LOCAL_SRC_FILES := com_raiing_childmodule_ChildModule.cpp utilities.c include $(BUILD_SHARED_LIBRARY)

    ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
    LOCAL_LDFLAGS := $(LOCAL_PATH)ccodearmeabi-v7alibCBBT.a LOCAL_LDFLAGS += $(LOCAL_PATH)ccodearmeabi-v7alibutilities.a 两者有 顺序

    比如:C:Program "${project_loc}/jni"

    -d
    以便在 run - external tools

    #LOCAL_STATIC_LIBRARIES := utilities

    endif

    需要修改上述内容的 LOCAL_MODULE:= 为希望的库名称。生成的库名将在这个名称前增加 lib 前缀。
    需要修改 LOCAL_SRC_FILES:= 将 jni 目录下的所有 cpp c 添加到后面,空格分隔。

    Application.mk 内容:
    APP_ABI := all 生成所有平台的目录文件,我们一般只需要三个

    APP_ABI := armeabi armeabi-v7a arm64-v8a
    APP_CFLAGS += -Wno-error=format-security -D_ENV_ANDROID_=1

    5. 添加 ndk 编译命令到项目。
    5-a. run - external tools - external tools configuration - program - new lanch configuration

    main- name: ndk_build

    main-location: ndk 安 装 目 录 dk-build.cmd 比如:S:work_dirandroid-ndk-r9d dk-build.cmd

    main- working directory: ${workspace_loc}/${project_name}/jni common - Display in favorites menu - 选中 External tools

    5-b. 选中 CTMProcess 项目名,project - properties - builders - import - ndk_build 5-d. 在 builders 中选中 ndk_build ,点击 UP,将 ndk_build 调整到最高。

    基本数据类型

    Java Type Native Type Description

    boolean jboolean

    byte jbyte

    char jchar

    double jdouble

    float jfloat

    int jint

    long jlong

    short jshort

    void void

    8 bits, unsigned 8 bits, signed
    16 bits, unsigned 64 bits

    32 bits
    32 bits, signed 64 bits, signed 16 bits, signed N/A

    Java Type

    Signature

    boolean Z

    byte B

    char C double D

    float F

    int I

    long J

    void V

    object Lfully-qualified-class; type[] [type
    method signature ( arg-types) ret-type

    Method

    Signature

    void f1()

    ()V

    int f2(int, long)
    

    (IJ)I

    boolean f3(int[])
    

    ([I)B

    double f4(String, int)
    
    (Ljava/lang/String;I)D
    
    void f5(int, String [], char)
    
    (I[Ljava/lang/String;C)V
    

    数据交互

    基本类型不需要转换,navtive 层直接可以使用,赋值到 c 里面需要强转,如 int uciT->cycleDays = (uint16) cycle_days;
    uint16 表示有符号,正数 int16 无符号正负都可以

    String 转换
    const char *= CBBT_getVersionString();

    char*转String
    jstring jstrBuf = env->NewStringUTF();
    String 转 char*
    char *filePath = (char *)(env->GetStringUTFChars(path, NULL)); 不用时需要释放
    ReleaseStringUTFChars(buf, jstrBuf);

    对象
    有 jobject 对象

    jclass cls = env->GetObjectClass(javaUCI);

    创建某个类对象

    jclass cls_acr = env->FindClass("com/raiing/cbbtjni/entity_jni/ACR_T"); jmethodID construct_acr = env->GetMethodID(cls_acr, "<init>", "()V"); jobject obj_acr = env->NewObject(cls_acr, construct_acr, "");

    给对象某个字段赋值,首先获取字段 id,再给字段赋值 jfieldID originFieldID = env->GetFieldID(cls_acr, "origin", "I"); env->SetIntField(obj_acr, originFieldID, (jint) acrT->origin); jfieldID extraDataFieldID = env->GetFieldID(cls, "extraData", "[B");

    对象集合 ArrayList<Entity>,给集合添加对象
    jclass cls_ArrayList = env->GetObjectClass(jobject);
    jmethodID arrayList_add = env->GetMethodID(cls_ArrayList, "add", "(Ljava/lang/Object;)Z");

    env->CallBooleanMethod(jobject, arrayList_add, obj_cbbt); env->DeleteLocalRef(obj_cbbt);

    获取集合里面的对象

    jmethodID arraylist_get = env->GetMethodID(cls_arraylist, "get", "(I)Ljava/lang/Object;"); jobject obj_uci = env->CallObjectMethod(jobject, arraylist_get, i); env->DeleteLocalRef(obj_uci);

    循环操作里面一定要删除引用,否则会有 512 的限制,如:jbytearray jstring jclass jobject

    数组类型数据赋值给 c 层
    jbyteArray extraData = (jbyteArray) env->GetObjectField(obj,

    extraDataFieldID);
    int size = env->GetArrayLength(extraData);

    jbyte *ed = (jbyte *) cbbt.extraData; env->GetByteArrayRegion(, 0, size, ed); env->DeleteLocalRef(extraData);

    c 层数组赋值给 java
    jbyteArray jbarray = env->NewByteArray(len); jbyte *jb = env->GetByteArrayElements(jbarray, 0); memcpy(jb, cbbt->extraData, len); env->SetByteArrayRegion(jbarray, 0, len, jb);

    输入输出

    c
    int8 ABBT_getExpectedDataRange(uint32 currentTime, int32 timeZone, uint32 *startTime, uint32 *endTime);
    java
    private native int getExpectedDataRange(long currentTime, long timeZone, Long startTime, Long endTime);

    cpp
    JNIEXPORT jint JNICALL Java_com_raiing_ABBTSurface_getExpectedDataRange(

    JNIEnv *env, jobject obj, jlong curTime, jlong timeZone,

    jobject startTime, jobject endTime)
    jclass cls = env->GetObjectClass(retObject);
    jmethodID codeMethodID = env->GetMethodID(cls, "<init>", "(J)V"); env->CallVoidMethod(startTime, codeMethodID, retLong);

    java 层错误的写法
    Integer startTime = 0;
    Integer endTime = 0;
    两者指向的同一个内存地址,再 c 层输出修改的时候,本来输出两个值,就变为了一个

    查看 ndk 崩溃 log
    需要的 So 文件在 objlocalarm64-v8alibCBBT.so

    S:Android_SDK dk-bundle oolchains Eclipse jni 提示

    异常问题
    建的工程没有 c/c++ build 支持,工程右键 android tools

    Log 占位符

    C 语言中输入输出函数占位符介绍 : 占位符 数据类型

    %d int
    %ld long int

    %c char

    %f float

    &lf double

    %x 十六进制

    %O 八进制

    %s 字符串

    --> Add native Support

    Project Properties -> C/C++ General -> Path and Symbols

    选择 include 标签,

    Add -> $Android_NDK_HOME/platforms/android-14/arch-arm/usr/include 任意版本

    选中 All languages.

    最后 Apply -> OK

    Log 测试不能输出 long uint64,需要分解为 uint32 LOGV("java2SYMPTOM->UEI_SYMPTOM_T 结构体 111: symptomTypeH jj

    h:%u,l:%u", (uint32)(symptomTypeH>>32),(uint32)(symptomTypeH));

    学习网址

    http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html http://home.pacifier.com/~mmead/jni/cs510ajp/index.html#JNI Data Types

    http://blog.csdn.net/woshinia/article/details/25132353

    http://blog.csdn.net/u012690435/article/details/38612461 参数传递 http://mysuperbaby.iteye.com/blog/1603817 DeleteLocalRef 问题

    http://www.oschina.net/question/2241352_213433 addr2line 定位 jni 问题行号 

  • 相关阅读:
    092、部署Graylog日志系统(2019-05-16 周四)
    091、万能的数据收集器 Fluentd (2019-05-15 周三)
    090、ELK完成部署和使用 (2019-05-13 周二)
    在CentOS7上无人值守安装Zabbix4.2
    089、初探ELK (2019-05-13 周一)
    34、Scrapy 知识总结
    33、豆瓣图书短评
    32、出任爬虫公司CEO(爬取职友网招聘信息)
    31、当当图书榜单爬虫
    30、吃什么不会胖
  • 原文地址:https://www.cnblogs.com/xiaorenwu702/p/5702772.html
Copyright © 2011-2022 走看看