zoukankan      html  css  js  c++  java
  • 02_jni_hello_c函数介绍

    介绍NDK平台都有哪些工具.通过NDK这套工具做安卓下的JNI开发.

    可能有一些需求更适合通过C去做,有一些功能要通过C去实现.一个安卓程序,它本身还是一个Java应用.有一些功能/方法不通过Java来实现了,这个方法要通过JNI去调C的代码.

     

    实际上安卓系统就是这么搞的.有JNI,Java才能调C/C++的函数.如果没有JNI,Java与C/C++之间沟通不了.所以JNI层安卓已经帮咱们实现好了.所以咱们实际上咱们在写这个代码的时候,包括放一个音乐,看这个视频都用到了JNI的技术.只不过人家封装好了,你不知道而已.既然人家都封装好了,那咱们还学什么呢?就直接用就完了嘛.它的这些C/C++开发的开源库不见得就会满足你的需求,可能安卓提供的这些C/C++的库不能满足你的需求.我现在想做一个特殊的加密逻辑,我想就放在C/C++开发的开源库,它安卓还没提供呢.那你就得自己写C/C++的代码.比如你想加一个人脸识别的需求,安卓目前没有人脸识别的功能.那你就得自己去搞C/C++的方法.搞C/C++的函数,然后通过JNI帮助咱们调到编译好的C/C++的模块.

    写代码:

     需求:通过点击一个按钮来调用C/C++的函数.

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    package com.example.hellojni;
    
    import android.app.Activity;
    import android.widget.TextView;
    import android.os.Bundle;
    
    
    public class HelloJni extends Activity
    {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
    
            /* Create a TextView and set its content.
             * the text is retrieved by calling a native
             * function.
             */
            TextView  tv = new TextView(this);
            tv.setText( stringFromJNI() );
            setContentView(tv);
        }
    
        /* A native method that is implemented by the
         * 'hello-jni' native library, which is packaged
         * with this application.
         */
        public native String  stringFromJNI();
    
        /* This is another native method declaration that is *not*
         * implemented by 'hello-jni'. This is simply to show that
         * you can declare as many native methods in your Java code
         * as you want, their implementation is searched in the
         * currently loaded native libraries only the first time
         * you call them.
         *
         * Trying to call this function will result in a
         * java.lang.UnsatisfiedLinkError exception !
         */
        public native String  unimplementedStringFromJNI();
    
        /* this is used to load the 'hello-jni' library on application
         * startup. The library has already been unpacked into
         * /data/data/com.example.hellojni/lib/libhello-jni.so at
         * installation time by the package manager.
         */
        static {
            System.loadLibrary("hello-jni");
        }
    }
        /* A native method that is implemented by the
         * 'hello-jni' native library, which is packaged
         * with this application.
         */
        public native String  stringFromJNI();

     本地方法是由一个叫hello-jni的native函数库来实现的,放在这个应用当中的.咱们最终写的这个C的代码,会打包生成一个native library,最终的实现都会放在这个native library里.


    NDK的samples是如何实现的?

    /*
     * Copyright (C) 2009 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     *
     */
    #include <string.h>
    #include <jni.h>
    
    /* This is a trivial JNI example where we use a native method
     * to return a new VM String. See the corresponding Java source
     * file located at:
     *
     *   apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
     */
    jstring
    Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                      jobject thiz )
    {
    #if defined(__arm__)
      #if defined(__ARM_ARCH_7A__)
        #if defined(__ARM_NEON__)
          #define ABI "armeabi-v7a/NEON"
        #else
          #define ABI "armeabi-v7a"
        #endif
      #else
       #define ABI "armeabi"
      #endif
    #elif defined(__i386__)
       #define ABI "x86"
    #elif defined(__mips__)
       #define ABI "mips"
    #else
       #define ABI "unknown"
    #endif
    
        return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
    }

    查看jni.h 

    /*
     * Reference types, in C.
     */
    typedef void*           jobject;
    typedef jobject         jclass;
    typedef jobject         jstring;
    typedef jobject         jarray;
    typedef jarray          jobjectArray;
    typedef jarray          jbooleanArray;
    typedef jarray          jbyteArray;
    typedef jarray          jcharArray;
    typedef jarray          jshortArray;
    typedef jarray          jintArray;
    typedef jarray          jlongArray;
    typedef jarray          jfloatArray;
    typedef jarray          jdoubleArray;
    typedef jobject         jthrowable;
    typedef jobject         jweak;

    jstring是jobject,jobject是void*.jobject它对应成一个任意类型的指针.Java的String它是一个对象,它并不是一个基本数据类型,所以它是存在在堆里面的.对一个Java的对象来讲,实际上在C里面是找不到这种对应的数据类型可以给它表示起来.但是因为jstring它是占据了这么一块连续的堆内存,所以说呢它就用一个任意类型的指针来表示这一个Java的字符串.只不过通过typedef给它起了一个别名,别名就叫做jstring.一看jstring就知道它对应Java的String类型.


    虽说natvie方法没传任何的参数

        /* A native method that is implemented by the
         * 'hello-jni' native library, which is packaged
         * with this application.
         */
        public native String  stringFromJNI();

    但是到了native方法实现就多了两个必传的参数

    jstring
    Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                      jobject thiz )

    第二个参数jobject还是void*.只要是C基本数据类型它都是void*.jobject只是一个别名,用来标记它是对应Java的Object这个类型.

    /*
     * Reference types, in C.
     */
    typedef void*           jobject;

    由哪一个Java类/对象调用的这个native方法,最终在C这边它就会作为一个参数jobject传进来.

    由于helloInC()是非静态的,是一个实例方法,必须得通过一个Java对象来进行调用.当前这个helloInC()方法是放在MainActivity里面,所以说你想运行它必须得保证一个MainActivity的实例才能调用这个helloInC().

     public native  String  helloInC();

     对于当前这个实例hello-jni来讲,jobject thiz是hello-jni.对于咱们要写的,jobject thiz是MainActivity.谁调用的native方法,最终这个jobject thiz就是谁.

    第一个参数JNIEnv* env,Env,之前获取SD卡的时候接触过这个词,Environment,环境的意思.实际上一个JNIEnv*就是一个JNI环境.jni.h里面也可以找到JNIEnv

    #else
    typedef const struct JNINativeInterface* JNIEnv;
    typedef const struct JNIInvokeInterface* JavaVM;
    #endif

    typedef自定义类型,它的类型是struct JNINativeInterface*.struct JNINativeInterface是一个结构体,后面多了一个*,说明它struct JNINativeInterface*是这个结构体的一级指针.struct JNINativeInterface是一个结构体,struct JNINativeInterface*是一个一级指针.一级指针struct JNINativeInterface*的别名是JNIEnv.

    JNIEnv* env

    JNIEnv*又加了一个星,说明env是结构体struct JNINativeInterface的二级指针.


    接口函数指针的表

    /*
     * Table of interface function pointers.
     */
    struct JNINativeInterface {
        void*       reserved0;
        void*       reserved1;
        void*       reserved2;
        void*       reserved3;
    
        jint        (*GetVersion)(JNIEnv *);
    
        jclass      (*DefineClass)(JNIEnv*, const char*, jobject, const jbyte*,
                            jsize);
        jclass      (*FindClass)(JNIEnv*, const char*);
    
        jmethodID   (*FromReflectedMethod)(JNIEnv*, jobject);
        jfieldID    (*FromReflectedField)(JNIEnv*, jobject);
        /* spec doesn't show jboolean parameter */
        jobject     (*ToReflectedMethod)(JNIEnv*, jclass, jmethodID, jboolean);
    
        jclass      (*GetSuperclass)(JNIEnv*, jclass);
        jboolean    (*IsAssignableFrom)(JNIEnv*, jclass, jclass);
    
        /* spec doesn't show jboolean parameter */
        jobject     (*ToReflectedField)(JNIEnv*, jclass, jfieldID, jboolean);
    
        jint        (*Throw)(JNIEnv*, jthrowable);
        jint        (*ThrowNew)(JNIEnv *, jclass, const char *);
        jthrowable  (*ExceptionOccurred)(JNIEnv*);
        void        (*ExceptionDescribe)(JNIEnv*);
        void        (*ExceptionClear)(JNIEnv*);
        void        (*FatalError)(JNIEnv*, const char*);
    
        jint        (*PushLocalFrame)(JNIEnv*, jint);
        jobject     (*PopLocalFrame)(JNIEnv*, jobject);
    
        jobject     (*NewGlobalRef)(JNIEnv*, jobject);
        void        (*DeleteGlobalRef)(JNIEnv*, jobject);
        void        (*DeleteLocalRef)(JNIEnv*, jobject);
        jboolean    (*IsSameObject)(JNIEnv*, jobject, jobject);
    
        jobject     (*NewLocalRef)(JNIEnv*, jobject);
        jint        (*EnsureLocalCapacity)(JNIEnv*, jint);
    
        jobject     (*AllocObject)(JNIEnv*, jclass);
        jobject     (*NewObject)(JNIEnv*, jclass, jmethodID, ...);
        jobject     (*NewObjectV)(JNIEnv*, jclass, jmethodID, va_list);
        jobject     (*NewObjectA)(JNIEnv*, jclass, jmethodID, jvalue*);
    
        jclass      (*GetObjectClass)(JNIEnv*, jobject);
        jboolean    (*IsInstanceOf)(JNIEnv*, jobject, jclass);
        jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
    
        jobject     (*CallObjectMethod)(JNIEnv*, jobject, jmethodID, ...);
        jobject     (*CallObjectMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jobject     (*CallObjectMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jboolean    (*CallBooleanMethod)(JNIEnv*, jobject, jmethodID, ...);
        jboolean    (*CallBooleanMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jboolean    (*CallBooleanMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jbyte       (*CallByteMethod)(JNIEnv*, jobject, jmethodID, ...);
        jbyte       (*CallByteMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jbyte       (*CallByteMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jchar       (*CallCharMethod)(JNIEnv*, jobject, jmethodID, ...);
        jchar       (*CallCharMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jchar       (*CallCharMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jshort      (*CallShortMethod)(JNIEnv*, jobject, jmethodID, ...);
        jshort      (*CallShortMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jshort      (*CallShortMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
        jint        (*CallIntMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jint        (*CallIntMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jlong       (*CallLongMethod)(JNIEnv*, jobject, jmethodID, ...);
        jlong       (*CallLongMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        jlong       (*CallLongMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
        jfloat      (*CallFloatMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
        jfloat      (*CallFloatMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
        jfloat      (*CallFloatMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
        jdouble     (*CallDoubleMethod)(JNIEnv*, jobject, jmethodID, ...) __NDK_FPABI__;
        jdouble     (*CallDoubleMethodV)(JNIEnv*, jobject, jmethodID, va_list) __NDK_FPABI__;
        jdouble     (*CallDoubleMethodA)(JNIEnv*, jobject, jmethodID, jvalue*) __NDK_FPABI__;
        void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
        void        (*CallVoidMethodV)(JNIEnv*, jobject, jmethodID, va_list);
        void        (*CallVoidMethodA)(JNIEnv*, jobject, jmethodID, jvalue*);
    
        jobject     (*CallNonvirtualObjectMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jobject     (*CallNonvirtualObjectMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        jobject     (*CallNonvirtualObjectMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
        jboolean    (*CallNonvirtualBooleanMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jboolean    (*CallNonvirtualBooleanMethodV)(JNIEnv*, jobject, jclass,
                             jmethodID, va_list);
        jboolean    (*CallNonvirtualBooleanMethodA)(JNIEnv*, jobject, jclass,
                             jmethodID, jvalue*);
        jbyte       (*CallNonvirtualByteMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jbyte       (*CallNonvirtualByteMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        jbyte       (*CallNonvirtualByteMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
        jchar       (*CallNonvirtualCharMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jchar       (*CallNonvirtualCharMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        jchar       (*CallNonvirtualCharMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
        jshort      (*CallNonvirtualShortMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jshort      (*CallNonvirtualShortMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        jshort      (*CallNonvirtualShortMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
        jint        (*CallNonvirtualIntMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jint        (*CallNonvirtualIntMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        jint        (*CallNonvirtualIntMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
        jlong       (*CallNonvirtualLongMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        jlong       (*CallNonvirtualLongMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        jlong       (*CallNonvirtualLongMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
        jfloat      (*CallNonvirtualFloatMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...) __NDK_FPABI__;
        jfloat      (*CallNonvirtualFloatMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list) __NDK_FPABI__;
        jfloat      (*CallNonvirtualFloatMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*) __NDK_FPABI__;
        jdouble     (*CallNonvirtualDoubleMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...) __NDK_FPABI__;
        jdouble     (*CallNonvirtualDoubleMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list) __NDK_FPABI__;
        jdouble     (*CallNonvirtualDoubleMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*) __NDK_FPABI__;
        void        (*CallNonvirtualVoidMethod)(JNIEnv*, jobject, jclass,
                            jmethodID, ...);
        void        (*CallNonvirtualVoidMethodV)(JNIEnv*, jobject, jclass,
                            jmethodID, va_list);
        void        (*CallNonvirtualVoidMethodA)(JNIEnv*, jobject, jclass,
                            jmethodID, jvalue*);
    
        jfieldID    (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);
    
        jobject     (*GetObjectField)(JNIEnv*, jobject, jfieldID);
        jboolean    (*GetBooleanField)(JNIEnv*, jobject, jfieldID);
        jbyte       (*GetByteField)(JNIEnv*, jobject, jfieldID);
        jchar       (*GetCharField)(JNIEnv*, jobject, jfieldID);
        jshort      (*GetShortField)(JNIEnv*, jobject, jfieldID);
        jint        (*GetIntField)(JNIEnv*, jobject, jfieldID);
        jlong       (*GetLongField)(JNIEnv*, jobject, jfieldID);
        jfloat      (*GetFloatField)(JNIEnv*, jobject, jfieldID) __NDK_FPABI__;
        jdouble     (*GetDoubleField)(JNIEnv*, jobject, jfieldID) __NDK_FPABI__;
    
        void        (*SetObjectField)(JNIEnv*, jobject, jfieldID, jobject);
        void        (*SetBooleanField)(JNIEnv*, jobject, jfieldID, jboolean);
        void        (*SetByteField)(JNIEnv*, jobject, jfieldID, jbyte);
        void        (*SetCharField)(JNIEnv*, jobject, jfieldID, jchar);
        void        (*SetShortField)(JNIEnv*, jobject, jfieldID, jshort);
        void        (*SetIntField)(JNIEnv*, jobject, jfieldID, jint);
        void        (*SetLongField)(JNIEnv*, jobject, jfieldID, jlong);
        void        (*SetFloatField)(JNIEnv*, jobject, jfieldID, jfloat) __NDK_FPABI__;
        void        (*SetDoubleField)(JNIEnv*, jobject, jfieldID, jdouble) __NDK_FPABI__;
    
        jmethodID   (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
    
        jobject     (*CallStaticObjectMethod)(JNIEnv*, jclass, jmethodID, ...);
        jobject     (*CallStaticObjectMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        jobject     (*CallStaticObjectMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
        jboolean    (*CallStaticBooleanMethod)(JNIEnv*, jclass, jmethodID, ...);
        jboolean    (*CallStaticBooleanMethodV)(JNIEnv*, jclass, jmethodID,
                            va_list);
        jboolean    (*CallStaticBooleanMethodA)(JNIEnv*, jclass, jmethodID,
                            jvalue*);
        jbyte       (*CallStaticByteMethod)(JNIEnv*, jclass, jmethodID, ...);
        jbyte       (*CallStaticByteMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        jbyte       (*CallStaticByteMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
        jchar       (*CallStaticCharMethod)(JNIEnv*, jclass, jmethodID, ...);
        jchar       (*CallStaticCharMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        jchar       (*CallStaticCharMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
        jshort      (*CallStaticShortMethod)(JNIEnv*, jclass, jmethodID, ...);
        jshort      (*CallStaticShortMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        jshort      (*CallStaticShortMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
        jint        (*CallStaticIntMethod)(JNIEnv*, jclass, jmethodID, ...);
        jint        (*CallStaticIntMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        jint        (*CallStaticIntMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
        jlong       (*CallStaticLongMethod)(JNIEnv*, jclass, jmethodID, ...);
        jlong       (*CallStaticLongMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        jlong       (*CallStaticLongMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
        jfloat      (*CallStaticFloatMethod)(JNIEnv*, jclass, jmethodID, ...) __NDK_FPABI__;
        jfloat      (*CallStaticFloatMethodV)(JNIEnv*, jclass, jmethodID, va_list) __NDK_FPABI__;
        jfloat      (*CallStaticFloatMethodA)(JNIEnv*, jclass, jmethodID, jvalue*) __NDK_FPABI__;
        jdouble     (*CallStaticDoubleMethod)(JNIEnv*, jclass, jmethodID, ...) __NDK_FPABI__;
        jdouble     (*CallStaticDoubleMethodV)(JNIEnv*, jclass, jmethodID, va_list) __NDK_FPABI__;
        jdouble     (*CallStaticDoubleMethodA)(JNIEnv*, jclass, jmethodID, jvalue*) __NDK_FPABI__;
        void        (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
        void        (*CallStaticVoidMethodV)(JNIEnv*, jclass, jmethodID, va_list);
        void        (*CallStaticVoidMethodA)(JNIEnv*, jclass, jmethodID, jvalue*);
    
        jfieldID    (*GetStaticFieldID)(JNIEnv*, jclass, const char*,
                            const char*);
    
        jobject     (*GetStaticObjectField)(JNIEnv*, jclass, jfieldID);
        jboolean    (*GetStaticBooleanField)(JNIEnv*, jclass, jfieldID);
        jbyte       (*GetStaticByteField)(JNIEnv*, jclass, jfieldID);
        jchar       (*GetStaticCharField)(JNIEnv*, jclass, jfieldID);
        jshort      (*GetStaticShortField)(JNIEnv*, jclass, jfieldID);
        jint        (*GetStaticIntField)(JNIEnv*, jclass, jfieldID);
        jlong       (*GetStaticLongField)(JNIEnv*, jclass, jfieldID);
        jfloat      (*GetStaticFloatField)(JNIEnv*, jclass, jfieldID) __NDK_FPABI__;
        jdouble     (*GetStaticDoubleField)(JNIEnv*, jclass, jfieldID) __NDK_FPABI__;
    
        void        (*SetStaticObjectField)(JNIEnv*, jclass, jfieldID, jobject);
        void        (*SetStaticBooleanField)(JNIEnv*, jclass, jfieldID, jboolean);
        void        (*SetStaticByteField)(JNIEnv*, jclass, jfieldID, jbyte);
        void        (*SetStaticCharField)(JNIEnv*, jclass, jfieldID, jchar);
        void        (*SetStaticShortField)(JNIEnv*, jclass, jfieldID, jshort);
        void        (*SetStaticIntField)(JNIEnv*, jclass, jfieldID, jint);
        void        (*SetStaticLongField)(JNIEnv*, jclass, jfieldID, jlong);
        void        (*SetStaticFloatField)(JNIEnv*, jclass, jfieldID, jfloat) __NDK_FPABI__;
        void        (*SetStaticDoubleField)(JNIEnv*, jclass, jfieldID, jdouble) __NDK_FPABI__;
    
        jstring     (*NewString)(JNIEnv*, const jchar*, jsize);
        jsize       (*GetStringLength)(JNIEnv*, jstring);
        const jchar* (*GetStringChars)(JNIEnv*, jstring, jboolean*);
        void        (*ReleaseStringChars)(JNIEnv*, jstring, const jchar*);
        jstring     (*NewStringUTF)(JNIEnv*, const char*);
        jsize       (*GetStringUTFLength)(JNIEnv*, jstring);
        /* JNI spec says this returns const jbyte*, but that's inconsistent */
        const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);
        void        (*ReleaseStringUTFChars)(JNIEnv*, jstring, const char*);
        jsize       (*GetArrayLength)(JNIEnv*, jarray);
        jobjectArray (*NewObjectArray)(JNIEnv*, jsize, jclass, jobject);
        jobject     (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);
        void        (*SetObjectArrayElement)(JNIEnv*, jobjectArray, jsize, jobject);
    
        jbooleanArray (*NewBooleanArray)(JNIEnv*, jsize);
        jbyteArray    (*NewByteArray)(JNIEnv*, jsize);
        jcharArray    (*NewCharArray)(JNIEnv*, jsize);
        jshortArray   (*NewShortArray)(JNIEnv*, jsize);
        jintArray     (*NewIntArray)(JNIEnv*, jsize);
        jlongArray    (*NewLongArray)(JNIEnv*, jsize);
        jfloatArray   (*NewFloatArray)(JNIEnv*, jsize);
        jdoubleArray  (*NewDoubleArray)(JNIEnv*, jsize);
    
        jboolean*   (*GetBooleanArrayElements)(JNIEnv*, jbooleanArray, jboolean*);
        jbyte*      (*GetByteArrayElements)(JNIEnv*, jbyteArray, jboolean*);
        jchar*      (*GetCharArrayElements)(JNIEnv*, jcharArray, jboolean*);
        jshort*     (*GetShortArrayElements)(JNIEnv*, jshortArray, jboolean*);
        jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
        jlong*      (*GetLongArrayElements)(JNIEnv*, jlongArray, jboolean*);
        jfloat*     (*GetFloatArrayElements)(JNIEnv*, jfloatArray, jboolean*);
        jdouble*    (*GetDoubleArrayElements)(JNIEnv*, jdoubleArray, jboolean*);
    
        void        (*ReleaseBooleanArrayElements)(JNIEnv*, jbooleanArray,
                            jboolean*, jint);
        void        (*ReleaseByteArrayElements)(JNIEnv*, jbyteArray,
                            jbyte*, jint);
        void        (*ReleaseCharArrayElements)(JNIEnv*, jcharArray,
                            jchar*, jint);
        void        (*ReleaseShortArrayElements)(JNIEnv*, jshortArray,
                            jshort*, jint);
        void        (*ReleaseIntArrayElements)(JNIEnv*, jintArray,
                            jint*, jint);
        void        (*ReleaseLongArrayElements)(JNIEnv*, jlongArray,
                            jlong*, jint);
        void        (*ReleaseFloatArrayElements)(JNIEnv*, jfloatArray,
                            jfloat*, jint);
        void        (*ReleaseDoubleArrayElements)(JNIEnv*, jdoubleArray,
                            jdouble*, jint);
    
        void        (*GetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
                            jsize, jsize, jboolean*);
        void        (*GetByteArrayRegion)(JNIEnv*, jbyteArray,
                            jsize, jsize, jbyte*);
        void        (*GetCharArrayRegion)(JNIEnv*, jcharArray,
                            jsize, jsize, jchar*);
        void        (*GetShortArrayRegion)(JNIEnv*, jshortArray,
                            jsize, jsize, jshort*);
        void        (*GetIntArrayRegion)(JNIEnv*, jintArray,
                            jsize, jsize, jint*);
        void        (*GetLongArrayRegion)(JNIEnv*, jlongArray,
                            jsize, jsize, jlong*);
        void        (*GetFloatArrayRegion)(JNIEnv*, jfloatArray,
                            jsize, jsize, jfloat*);
        void        (*GetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
                            jsize, jsize, jdouble*);
    
        /* spec shows these without const; some jni.h do, some don't */
        void        (*SetBooleanArrayRegion)(JNIEnv*, jbooleanArray,
                            jsize, jsize, const jboolean*);
        void        (*SetByteArrayRegion)(JNIEnv*, jbyteArray,
                            jsize, jsize, const jbyte*);
        void        (*SetCharArrayRegion)(JNIEnv*, jcharArray,
                            jsize, jsize, const jchar*);
        void        (*SetShortArrayRegion)(JNIEnv*, jshortArray,
                            jsize, jsize, const jshort*);
        void        (*SetIntArrayRegion)(JNIEnv*, jintArray,
                            jsize, jsize, const jint*);
        void        (*SetLongArrayRegion)(JNIEnv*, jlongArray,
                            jsize, jsize, const jlong*);
        void        (*SetFloatArrayRegion)(JNIEnv*, jfloatArray,
                            jsize, jsize, const jfloat*);
        void        (*SetDoubleArrayRegion)(JNIEnv*, jdoubleArray,
                            jsize, jsize, const jdouble*);
    
        jint        (*RegisterNatives)(JNIEnv*, jclass, const JNINativeMethod*,
                            jint);
        jint        (*UnregisterNatives)(JNIEnv*, jclass);
        jint        (*MonitorEnter)(JNIEnv*, jobject);
        jint        (*MonitorExit)(JNIEnv*, jobject);
        jint        (*GetJavaVM)(JNIEnv*, JavaVM**);
    
        void        (*GetStringRegion)(JNIEnv*, jstring, jsize, jsize, jchar*);
        void        (*GetStringUTFRegion)(JNIEnv*, jstring, jsize, jsize, char*);
    
        void*       (*GetPrimitiveArrayCritical)(JNIEnv*, jarray, jboolean*);
        void        (*ReleasePrimitiveArrayCritical)(JNIEnv*, jarray, void*, jint);
    
        const jchar* (*GetStringCritical)(JNIEnv*, jstring, jboolean*);
        void        (*ReleaseStringCritical)(JNIEnv*, jstring, const jchar*);
    
        jweak       (*NewWeakGlobalRef)(JNIEnv*, jobject);
        void        (*DeleteWeakGlobalRef)(JNIEnv*, jweak);
    
        jboolean    (*ExceptionCheck)(JNIEnv*);
    
        jobject     (*NewDirectByteBuffer)(JNIEnv*, void*, jlong);
        void*       (*GetDirectBufferAddress)(JNIEnv*, jobject);
        jlong       (*GetDirectBufferCapacity)(JNIEnv*, jobject);
    
        /* added in JNI 1.6 */
        jobjectRefType (*GetObjectRefType)(JNIEnv*, jobject);
    };

     首先看看它struct JNINativeInterface声明的结构.

      jint        (*GetVersion)(JNIEnv *);

    jint是返回值,GetVersion是函数指针的名字,JNIEnv  *是形参的类型.

     jint        (*Throw)(JNIEnv*, jthrowable);

     jint是返回值,Throw是函数指针的名字,JNIEnv*, jthrowable是形参的类型.

    这里就定义了一堆函数指针,这些函数指针就可以帮助咱们做JNI的开发.

    这些功能实际上都是通过JNINativeInterface这里面定义的这些函数指针来实现的.实际上就类似于一个函数表.这里面就可以调用到JNI开发常用的函数,通过函数指针来进行调用的.


    C的源代码直接使用肯定是不行的,必须得把它编译.

    #include  <stdlib.h>
    #include <stdio.h>
    
    /*int main(int argc, char **argv) {//main是程序的入口.
    //但是今天java才是程序的入口,只不过是把一个方法通过C来实现.所以在C这边只需要写一个函数.
    //那这个函数是对我native方法的具体实现.
    //今天程序的入口是咱们的安卓应用.所以不能用main.
    }
    */
    
    /*char*  helloInC(){//人家java要的是String,你的是char *;你的helloInC怎么对java那边的helloInC().
    //char *和String还是有点区别的.
    //java的String一定是丢在堆内存里面的,C的char *不一定丢在堆内存里面,有可能在栈里面.
    //所以实际上char *和String不是一种类型.所以这么写也不靠谱.
    
    }
    */
    //本地函数命名规则 Java_包名_native函数所在类的类名_native方法名
    //第二个参数jobject thiz  就是调用当前native方法的java对象.
    //第一个参数 JNIEnv* JNIEnv是结构体  JNINativeInterface这个结构体的一级指针
    //env又是JNIEnv的一级指针 那么env就是JNINativeInterface的二级指针
    //结构体JNINativeInterface定义了大量的函数指针  这些函数指针在JNI开发中十分常用.
    //这些功能实际上都是通过JNINativeInterface这里面定义的这些函数指针来实现的.实际上就类似于一个函数表.这里面就可以调用到JNI开发常用的函数,通过函数指针来进行调用的.
    //调用函数的第一种方法:(**env).func
    //第二种方式:(*env)->
    //jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
       //                                               jobject thiz )
    //jString是Java的String类型在C里面具体的表示的方式.
    jstring Java_com_itheima_hello_MainActivity_helloInC( JNIEnv* env,
                                                      jobject thiz ){
    //就得调用(*env)里面的函数指针实现相关的功能
        //有没有哪一个函数指针它的返回值是一个jstring.
        //       jstring     (*NewStringUTF)(JNIEnv*, const char*);
        char* str ="hello from c!!!!!";//C的环境只能定义char*
        //得把char*转化成一个jstring类型才能返回.这些功能实际上都在这个JNIEnv所指向的这个JNINativeInterface里面.
        //通过newStringUTF  方法把C的字符串  转换成java的jstring类型.
        return (*env)->NewStringUTF(env,str);//(*env)->转化成一级指针调用
    
    }
    package com.itheima.hello;
    
    import android.os.Bundle;
    import android.app.Activity;
    import android.view.Menu;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        public  void jniHello(View v){//Java不实现,只声明.
            //通过这个声明去调到C的方法.所以在Java这边去搞一个函数的声明.
            //调用恁地方法  并且把返回的值通过吐司显示出来
            Toast.makeText(this, helloInC(), Toast.LENGTH_SHORT).show();//拿到C返回的字符串.
        }
        //public abstract String helloInC();//不能用抽象,abstract还不行.
        //用关键字native声明一个放在C这边的函数  通过native关键字声明了一个本地方法.
        //本地方法不用实现,需要用jni帝爱用C的代码来实现  
        public native  String  helloInC();
    }
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context=".MainActivity" >
    
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="jniHello"
            android:text="调用C的函数" />
    
    </RelativeLayout>
  • 相关阅读:
    【002】有符号数据传递给无符号变量
    C++第二课 数据类型和常变量
    【001】冒泡排序
    iOS中为网站添加图标到主屏幕以及增加启动画面
    _stdcall,_cdecl区别
    解决表格里面使用text-overflow后依旧不能隐藏超出的文本
    windows7 64位下运行 regsvr32 注册ocx或者dll的方法
    在sqlite中使用索引
    ASP中 Request.Form中文乱码的解决方法
    html——标签基础
  • 原文地址:https://www.cnblogs.com/ZHONGZHENHUA/p/7192636.html
Copyright © 2011-2022 走看看