zoukankan      html  css  js  c++  java
  • JNI_Android项目中调用.so动态库实现详解

    转自:http://www.yxkfw.com/?p=7223

    1. 在Eclipse中创建项目:TestJNI

    2. 新创建一个class:TestJNI.java

    package com.wwj.jni;
    
    public class TestJNI {
        public native boolean Init();
        public native int Add(int x, int y);
        public native void Destory();
    }
    以上代码声明三个本地方法。
     
    3. 编译JNI
    找到Android项目中bin目录下,会有classes文件夹,Eclipse自动为我们生成的字节码文件就在这个目录下。
    我们在该路径下,使用javah命令,生成我们想要得到的.h头文件,如下图所示:
    执行javah -jni com.wwj.jni.TestJNI命令之后,会在classes目录下生成头文件:com_wwj_jni_TestJNI.h
    将它复制到jni文件夹下,打开如下:
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class com_wwj_jni_TestJNI */
    
    #ifndef _Included_com_wwj_jni_TestJNI
    #define _Included_com_wwj_jni_TestJNI
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     com_wwj_jni_TestJNI
     * Method:    Init
     * Signature: ()Z
     */
    JNIEXPORT jboolean JNICALL Java_com_wwj_jni_TestJNI_Init
      (JNIEnv *, jobject);
    
    /*
     * Class:     com_wwj_jni_TestJNI
     * Method:    Add
     * Signature: (II)I
     */
    JNIEXPORT jint JNICALL Java_com_wwj_jni_TestJNI_Add
      (JNIEnv *, jobject, jint, jint);
    
    /*
     * Class:     com_wwj_jni_TestJNI
     * Method:    Destory
     * Signature: ()V
     */
    JNIEXPORT void JNICALL Java_com_wwj_jni_TestJNI_Destory
      (JNIEnv *, jobject);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    以上代码就是通过javah命令生成jni层代码。
     
    4. 使用C/C++实现JNI
    在jni文件夹下,创建com_wwj_jni_TestJNI.h对应的cpp文件:com_wwj_jni_TestJNI.cpp
     
    我们再添加两个文件Add.h,Add.cpp,具体实现放在这两个文件中来完成。
    Add.h
    #ifndef _TEST_JNI_ADD_H_
    #define _TEST_JNI_ADD_H_
    
    class CAdd {
    public:
        CAdd();
        ~CAdd();
    
        int Add(int x, int y);
    };
    
    #endif

    Add.cpp

    #include "Add.h"
    
    CAdd::CAdd() {
    
    }
    
    CAdd::~CAdd() {
    
    }
    
    int CAdd::Add(int x, int y) {
        return x + y;
    }

    com_wwj_jni_TestJNI.cpp的实现:

    #include <stdio.h>
    #include <stdlib.h>
    #include "com_wwj_jni_TestJNI.h"
    #include "Add.h"
    
    CAdd *pCAdd = NULL;
    
    JNIEXPORT jboolean JNICALL Java_com_wwj_jni_TestJNI_Init(JNIEnv *env,
            jobject obj) {
        if (pCAdd == NULL) {
            pCAdd = new CAdd;
        }
        return pCAdd != NULL;
    }
    
    JNIEXPORT jint JNICALL Java_com_wwj_jni_TestJNI_Add(JNIEnv *env, jobject obj,
            jint x, jint y) {
        int res = -1;
        if (pCAdd != NULL) {
            res = pCAdd->Add(x, y);
        }
        return res;
    }
    
    JNIEXPORT void JNICALL Java_com_wwj_jni_TestJNI_Destory(JNIEnv *env, jobject obj)
    {
        if (pCAdd != NULL)
        {
            pCAdd = NULL;
        }
    }
    5. 创建mk文件,并使用ndk-build命令生成.so动态链接库文件
    在jni目录下创建Android.mk文件如下:
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := TestJNI
    
    LOCAL_SRC_FILES := com_wwj_jni_TestJNI.cpp
    LOCAL_SRC_FILES += Add.cpp
    
    include $(BUILD_SHARED_LIBRARY)
    其中
    LOCAL_PATH是C/C++代码所在目录,也就是我们的jni目录。
    LOCAL_MODULE是要编译的库的名称。编译器会自动在前面加上lib,在后面加上.so。
    LOCAL_SRC_FILES是要编译的C/C++文件。
     
    然后我还需要在Android项目根目录下创建Application.mk文件:
    APP_PROJECT_PATH := $(call my-dir)
    APP_MODULES := TestJNI
    写完了这两个mk文件,我们就可以用ndk来为我们生成相应的动态链接库了。前提你需要下载NDK,并把NDK路径配置到path环境变量中去,笔者配置的路径是:D:Cocos2dxandroid-ndk-r9d,具体视个人情况而定。
    进入Application.mk文件所在目录,在命令行中使用ndk-build生成.so文件
    编译成功后会在工程目录的libs/armeabi目录下生成一个libTestJNI.so文件。
     
    项目结构会变成如下:
    6. 在Java中调用JNI
    package com.wwj.jni;
    
    import android.os.Bundle;
    import android.widget.TextView;
    import android.app.Activity;
    
    public class TestJNIActivity extends Activity {
    
        private TextView textView;
        static {
            // 加载动态库
            System.loadLibrary("TestJNI");
        }
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            textView = (TextView) findViewById(R.id.textview);
    
            TestJNI testJNI = new TestJNI();
            // 调用native方法
            boolean init = testJNI.Init();
            if (init == true) {
                // 调用Add函数
                int sum = testJNI.Add(100, 150);
                textView.setText("你真是个" + sum);
            } else {
                textView.setText("你比二百五还要二百五");
            }
            testJNI.Destory();
        }
    }

    运行项目,效果图如下:

  • 相关阅读:
    topcoder srm 445 div1
    topcoder srm 440 div1
    topcoder srm 435 div1
    topcoder srm 430 div1
    topcoder srm 400 div1
    topcoder srm 380 div1
    topcoder srm 370 div1
    topcoder srm 425 div1
    WKWebView强大的新特性
    Runtime那些事
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/6154945.html
Copyright © 2011-2022 走看看