zoukankan      html  css  js  c++  java
  • 01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用

    1 什么是JNI

    JNI Java本地开发接口

    JNI是一个协议,这个协议用来沟通java代码和外部的本地代码(C/C++)

    通过这个协议,java代码就能够调用外部的C/C++代码,外部的C/C++代码也能够调用Java代码。

    2 为什么用JNI

    1  JNI扩展了java虚拟机的能力,驱动开发(wifi-hotspot)2.3无线热点共享

    2  Native code效率高,数学运算,实时渲染的游戏上。音视频处理(极品飞车),opengl,ffmpeg

    3  复用代码(文件压缩。人脸识别)

    4  特殊的业务场景

    3 怎么用JNI

    1 C/C++语言

    2 掌握java ini流程

    3 NDK(native develop kits)

    5 配置cygwin64的环境变量的方式是编写Cygwinetcprofile,ndk的路径配置到path里面,截图例如以下:

    打开Cygwin输入:Make –v,结果例如以下:

    显示出来GNI Make的版本号。说明我们的cygwin模拟的Linux编辑环境模拟成功。

    输入ndk-build。出现以下结果:

    显示出上面的效果,说明环境变量已经配置好了。

     

    6 相同能够将这个变量配置到windows下的环境变量中:配置例如以下:

    进入CMD命令行窗体中,假设出现以下结果,说明配置成功:

     

    当配置了第6步之后。若cygwin没有配置成功时,也能够在window中的cmd命令行中使用ndk-build.

     

    7 jni中的数据类型(后面是Java中的类型,左边是C语言中的类型):

    #ifdef HAVE_INTTYPES_H

    # include <inttypes.h>      /* C99 */

    typedef uint8_t         jboolean;       /* unsigned 8 bits */

    typedef int8_t          jbyte;          /* signed 8 bits */

    typedef uint16_t        jchar;          /* unsigned 16 bits */

    typedef int16_t         jshort;         /* signed 16 bits */

    typedef int32_t         jint;           /* signed 32 bits */

    typedef int64_t         jlong;          /* signed 64 bits */

    typedef float           jfloat;         /* 32-bit IEEE 754 */

    typedef double         jdouble;        /* 64-bit IEEE 754 */

    #else

    typedef unsigned char   jboolean;       /* unsigned 8 bits */

    typedef signed char     jbyte;          /* signed 8 bits */

    typedef unsigned short  jchar;          /* unsigned 16 bits */

    typedef short          jshort;         /* signed 16 bits */

    typedef int            jint;           /* signed 32 bits */

    typedef long long      jlong;          /* signed 64 bits */

    typedef float          jfloat;         /* 32-bit IEEE 754 */

    typedef double        jdouble;        /* 64-bit IEEE 754 */

    #endif

     

    /* "cardinal indices and sizes" */

    typedef jint            jsize;

    8 案例效果(以下的土司是调用C语言代码显示的):

    接下来编写案例。使用java代码调用C代码,创建项目helloworldformc,代码结构例如以下:

    当中libs下的内容例如以下:

    9 编写MainActivity,代码例如以下:

    package com.example.helloworldformc;

     

    import android.app.Activity;

    import android.os.Bundle;

    import android.view.View;

    import android.widget.Toast;

     

    public class MainActivity extends Activity {

             // 1 定义一个c方法的接口   相当于在java代码中定义了一个接口

             //接口的实现方法是C语言实现的

             public native String helloWorldFromC();

              
             // 变态命名
             public native String hello_world_from_c();


             // 5 步在java代码中 引入库函数

             static{

                       System.loadLibrary("hello");// 注意事项 去掉前面的lib 后面的.so

             }

            

             @Override

             protected void onCreate(Bundle savedInstanceState) {

                       super.onCreate(savedInstanceState);

                       setContentView(R.layout.activity_main);

             }

            

             public void click(View view){

                       // 弹出一个土司 土司的内容 c代码写出来       

                       // 6

                       Toast.makeText(getApplicationContext(), helloWorldFromC(), 0).show();

             }

    }

    10 在项目下创建一个jni文件夹(这个是必须的),開始编写Hello.c,代码例如以下:

    #include <stdio.h>

    #include <jni.h>

     

    /*

     * 相应的是:public native String helloWorldFromC(){}

     * jstring:表示的是返回的是String类型的

     * 函数名称规则是:Java_包名_类名_方法名。

     *

     * 注意:包名之间的"."在以下要变成下划线

     */

    jstring Java_com_example_helloworldformc_MainActivity_helloWorldFromC(JNIEnv* env,jobject obj) {

        //2  实现C代码

        //返回一个java String类型的字符串,使用一下函数

        //jstring     (*NewStringUTF)(JNIEnv*, const char*);

        //(*env) 相当于 JNINativeInterface* JNIEnv

        //*(*env)  相当于 JNINativeInterface

     

        //能够通过以下两种方式返回參数

        //return (**env).NewStringUTF(env,"helloworldfromc");

     

        return  (*env)->NewStringUTF(env,"helloworldfromc");

     

        //android.mk 告诉编译器  怎样把C代码打包成函数库

        //3 生成.mk文件

        //4   C代码  打包成函数库

    }


    /*这里JNIEXPORT表示的是通过工具生成的。这时候也能够将JNIEXPORT去掉*/

    JNIEXPORT jstring JNICALL Java_com_example_helloworldformc_MainActivity_hello_1world_1from_1c


     (JNIEnv * env, jobject obj){


    }



    注意:上面的这个源文件的类名也能够通过javah命令生成,生成步骤例如以下:

    (1)       假设JDK使用的是1.6,使用javah命令前要到达:项目文件夹inclasses文件夹下

    (2)       假设JDK使用的是1.7,使用javah命令前要达到:项目文件夹insrc文件夹下:

    比如(我使用的是JDK1.7)

    在项目中生成.h


    11 Android.mk文件的内容例如以下:

    #一个Android.mk文件必须以下这个变量开头,它用于定位

    #它用于定位你的源文件,my-dir这个宏是构件系统提供的,

    #它用于返回当前文件夹的路径(这个文件夹包括Android.mk它自己)

    LOCAL_PATH := $(call my-dir)

     

    #CLEAR_VARS也是build system构件系统提供的,指定到一个指定的GNU Makefile文件

    #这个Makefile文件帮你去清除一些LOCAL_XXX变量(比方:LOCAL_MODULE,LOCAL_SRC_FILES

    #,LOCAL_STATIC_LIBRARIES.等等...),除了LOCAL_PATH.

    include $(CLEAR_VARS)

     

    #LOCAL_MODULE变量必须在你的Android.mk文件里定义。名称必须唯一

    #而且不能包括一些空格,要注意的是构件系统会自己主动的加入适当的前缀和前缀

    #换一句话说。一个命名为"foo"的共享库模块。会被生成"libfoo.so"文件。

    #重要提示:假设你定义的模块名称是"libfoo",构建系统将不会加入"lib"前缀,

    #而且也会生成"libfoo.so"文件。

    LOCAL_MODULE    := hello

     

     

    #LOCAL_SRC_FILES变量必须包括一个C或者C++的源文件集合,这些文件终于会被用于

    #生成一个module,注意的是,这里不应该有头文件和包括文件,由于构件系统自己主动为您

    #加入这些文件。仅仅须要列出源文件即可了。

     

    #注意:默认的C++源文件的后缀名是.cpp,相同你也能够通过LOCAL_CPP_EXTENSION来自己定义

    #CPP的后缀名(比如:".cxx"能够,"cxx"不能够)

    LOCAL_SRC_FILES := Hello.c

     

    include $(BUILD_SHARED_LIBRARY)

    12 接下来使用cygwin,使用ndk-build来编译程序

    1)、如想将c变成.so的库,须要使用ndk-build命令

    2)、将路径路径切换到project文件夹下。

    3)、然后运行ndk-build这个操作(这个操作直接指定到项目路径下就能够了)

    注意:在使用这个ndk-build功能之前,须要有Android.mk文件(告诉编译器,怎样将C代码打包成函数库。详细的Android.mk怎么使用能够看ndk中的Android.html文档)

     

    
  • 相关阅读:
    struts2基础
    hibernate框架基础
    Django的模板层
    HBuilder无法连接夜神模拟器的解决办法
    Django的视图层
    Django的路由层
    Django简介
    http协议
    web应用
    Mongodb之增删改查
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6792499.html
Copyright © 2011-2022 走看看