zoukankan      html  css  js  c++  java
  • about JNI

    1、Java对C/C++事件处理的封装
    JIT(Just in Time、Java语言的原动态编译技术)

    大多数的游戏引擎都是使用可移植的C语言开发的,然后通过简单的封装以适应特殊的平台。

    2、Android.mk文件描述了要编译的原生库的模块名称和所需的源文件。

    3、
    JNIEnv* env : 对JNI环境的引用
    jclass class : 对需要调用原生函数的Java类的引用
    jobjectArray jargv : 对Java传进来的字符串数组参数的引用,被封装成JNI的jobjectArray类型。
    通过它来提取从Java层传递过来的字符串,并将它们发送到原生main函数。


    lib.c 包含原生库的主要代码
    Android.mk Android的生成文件(makefile),用于构建原生库。

    LOCAL_PATH : 必须位于文件的最开始。用来定位源文件的位置,返回当前目录的路径

    相应的Android.mk文件会象下面这样:

    ---------- cut here ------------------

    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE:= helloworld

    LOCAL_SRC_FILES := helloworld.c

    include $(BUILD_SHARED_LIBRARY)

    ---------- cut here ------------------

    关于LOCAL_CFLAGS
    在某些时候,编译源码需要定义宏变量,这个时候,我们可以直接在对应的源码里面去修改,但也有一些情况,我们是没法在别人的源码里定义宏变量的,这个时候,就需要使用到LOCAL_CFLAGS 了 ,举例如下:

    LOCAL_CFLAGS += -D__FAVOR_BSD

    这行代码的作用就是在原有的cflags基础上,再定义一个宏变量__FAVOR_BSD

    类似于#define __FAVOR_BSD

    include $(BUILD_SHARED_LIBRARY)是用来指示将当前模块编译为共享库,前缀为lib,后缀为.so。
    还有另外一个BUILD_STATIC_LIBRARY,是用来指示将当前模块编译为静态库的,前缀为.a,后缀为.a。

     ============================================================================

    最近在移植一个linux下的c库到android,学习编写Android.mk文件,特地花了点时间学习。

    在网上搜了很多,最后发现还是看ndk的文档最直接,也最全面,下面的总结主要是根据ndk提供的文档编写的。

    1、单一的Android.mk文件:

    LOCAL_PATH := $(call my-dir)

    include $(CLEAR_VARS)

    LOCAL_MODULE := hello-jni
    LOCAL_SRC_FILES := hello-jni.c

    include $(BUILD_SHARED_LIBRARY)

    LOCAL_PATH必须位于Android.mk文件的最开始。它是用来定位源文件的位置,$(call my-dir)的作用就是返回当前目录的路径。

    include $(CLEAR_VARS)的作用是清除一些变量的值,但是LOCAL_PATH除外。

    LOCAL_MODULE是用来指定当前待编译模块的名称,在示例中的模块名称为hello-jni

    LOCAL_SRC_FILES是用来指定参与编译的源代码文件。这里只编译hell0-jin.c

    include $(BUILD_SHARED_LIBRARY)是用来指示将当前模块编译为共享库,前缀为lib,后缀为.so。
    还有另外一个BUILD_STATIC_LIBRARY,是用来指示将当前模块编译为静态库的,前缀为.a,后缀为.a。

    这就是一个最简单的Android.mk的结构。可能还有另外一点需要介绍:
    LOCAL_C_INCLUDES:=include 这个是用来指定在编译时即将使用的c头文件的位置,以当前目录为起点。

    2、定义多个Android.mk文件。
    有的时候,需要编译的模块比较多,我们可能会将对应的模块放置在相应的目录中,这样,我们可以在每个目录中定义对应的Android.mk文件(类似于上面的写法),最后,在根目录放置一个Android.mk文件,内容如下:

    include $(call all-subdir-makefiles)

    只需要这一行就可以了,它的作用就是包含所有子目录中的Android.mk文件

    3、也可以在一个Android.mk文件里包含多个模块。
    很直观的想法就是将第一个Android.mk文件的内容复制一份,然后修改。我最开始也是这样做的,但是后来出现问题了,在第二个模块中的源码找不到,最后还是看文档,发现里面已经有示例解释了:

    LOCAL_PATH := $(call my-dir)


    IMPORTANT NOTE: Due to the way GNU Make works, this really returns
    the path of the *last* *included* *Makefile* during the parsing of
    build scripts. Do not call my-dir after including another file.

    大意是:基于GNU make的工作方式,$(call my-dir)会返回在解析build脚本时,遇到的最后一个 include中涉及的目录。

    所以,很多时候,在这个Android.mk里面只需要调用一次$(call my-dir)就够了,如果所有的源文件都在一个目录中。

    如果需要的话,可以在第一次调用call my-dir的时候,将值保存下来,比如:

    MY_LOCAL_PATH := $(call my-dir)


    LOCAL_PATH := $(MY_LOCAL_PATH)

    然后,在另外一个模块中,继续如下定义:

    LOCAL_PATH := $(MY_LOCAL_PATH)

    在编译一般的c源代码时,上面的基本可以满足了,等后面需要,再继续补充吧!

    补充:
    关于LOCAL_CFLAGS
    在某些时候,编译源码需要定义宏变量,这个时候,我们可以直接在对应的源码里面去修改,但也有一些情况,我们是没法在别人的源码里定义宏变量的,这个时候,就需要使用到LOCAL_CFLAGS 了 ,举例如下:

    LOCAL_CFLAGS += -D__FAVOR_BSD

    这行代码的作用就是在原有的cflags基础上,再定义一个宏变量__FAVOR_BSD

    类似于#define __FAVOR_BSD

    ======================================================================

    JNI类型

    1、基本数据类型
    boolean - jboolean - unsigned 8 bits
    byte - jbyte - signed 8 bits
    char - jchar - unsigned 16 bits
    short - jshort - signed 16 bits
    int - jint - signed 32 bits
    long - jlong - signed 64 bits
    float - jfloat - 32 bits
    double - jdouble - 64 bits

    2、引用类型
    当在C语言中使用时,所有的JNI引用类型都被定义为jobject类型


    int[]在JNI中的表示[I
    int[][]在JNI中的表示[[I


    基本类型的域
    Z boolean
    B byte
    C char
    S short
    I int
    J long
    F float
    D double

    引用类型的域
    Ljava/lang/String; - String
    [I - int[]
    [Ljava/lang/Object Object[]

    Method说明
    JNI方法声明规则:先写参数列表,再写返回类型
    String f() - ()Ljava/lang/String;
    long f(int i, Class c) - (ILjava/lang/Class;)J
    String(byte[] bytes) - ([B)Ljava/lang/String;

  • 相关阅读:
    #333 Div2 Problem B Approximating a Constant Range(尺取法)
    苦逼的单身狗(玄乎的尺取大法)
    欧拉项目第四题之三位数之积数的最大回数
    欧拉项目第三题之最大质数因子
    关于尺取法的认识与简单例题
    codeforces 980B Marlin
    康托展开和逆康托展开
    Chrome控制台中Network的Preview与Response区别
    配置Express中间件
    Express中间件简介
  • 原文地址:https://www.cnblogs.com/MyGameAndYOU/p/3957668.html
Copyright © 2011-2022 走看看