C++ Android 經過JNI 雙向調用注意事項

在通常的APP項目中,都不用用到C++  因此當咱們須要使用C++(也就是JNI)的時候 須要在 Android studio 中進行以下設置java

(這裏須要特別注意下  若是你的 Android studio版本是3.0及以上時,那麼原來3.0如下的版本 在運行項目時會提示 「No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi」  linux

個人解決方法是  在3.0如下的版本點擊安裝 CMAKE,NDK,3.0以上的項目也沒有報錯)android

補充:https://developer.android.google.cn/ndk/downloads/  下載替換 本身sdk 中 toolchains 文件夾,及android-ndk-r16b-windows-x86_64\android-ndk-r16b\toolchains 中的文件就能夠解決上面的問題windows

方法有兩種:app

(1)File --> Settings --> Appearance & Behavior --> System Settings --> Android SDK -->勾選CMAKE,NDKide

(2)ctrl+alt+S -->搜索框中 輸入 SDK -->勾選CMAKE,NDK函數

 以下圖:this

 

配置作完後 在擼代碼以前 咱們來對 java類型與C++類型的比較google

/*
    *
    *
       Java類型      別名             C++本地類型          字節(bit)


       boolean      jboolean            unsigned char         8, unsigned

       byte         jbyte               signed char       8

       char         jchar               unsigned short        16, unsigned

       short        jshort              short                 16

       int          jint                long               32

       long         jlong               __int64            64

       float        jfloat              float               32

       double       jdouble             double              64

       void         void                                   n/a

*
    * */

 

開始正式擼代碼  (若是你們想快速生成JNI範例   在新建項目時勾選 include C++ 就能夠idea

MainActivity.java

public class MainActivity extends AppCompatActivity { // Used to load the 'native-lib' library on application startup. static { System.loadLibrary("native-lib");//此.so名稱名稱能夠在 CMakeLists.txt 中修改 } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Example of a call to a native method TextView tv = (TextView) findViewById(R.id.sample_text); tv.setText(stringFromJNI()); tv.setText(testNativeFunction()); } /** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */ public native String stringFromJNI(); public native String testNativeFunction();
public native String cCallJava();

public native String cCallJavaParm();
/*
    * java調用有參方法
    */
    public static  Object cByJava(int b){
        Log.i("cByJava", "cByJava: 我被調用了  b:"+b);
        return "ssssss";
    }


    public static void cByJavaf(){
        Log.i("cByJava1", "cByJava: 我被調用了 ");
    }
  public  void     addffffff(int b,int c,int d){
  Log.i("bbbbb","fffffff");
  }
}

  native-lib.cpp

 

#include <jni.h>
#include <string>


#define  NativeStr(name)Java_com_example_android_testc_##name

/*
    *
    *
       類型           相應的簽名:(就是後面的 GetStaticMethodID(mMain,"cByJava","(I)Ljava/lang/Object;") 的 (I)Ljava/lang/Object;)

       boolean        Z

       byte           B

       char           C

       short          S

       int            I

       long           J

       float          F

       double         D

       void           V

       object         L用/分隔包的完整類名:   Ljava/lang/String;

       Array          [簽名          [I      [Ljava/lang/Object;

       Method         (參數1類型簽名 參數2類型簽名···)返回值類型簽名





    *
    * */



extern "C" JNIEXPORT
jstring JNICALL
        NativeStr(MainActivity_stringFromJNI)(
        JNIEnv *env,
        jobject /* this */) {

    //C++調用java  帶參數 有返回值(當返回值爲String時用Object代替)
    //----------------beigin----------------
//    static const char* const DL_CLASS_NAME = "com/example/android/testc/MainActivity";
//    jclass  mMain = (env)->FindClass(DL_CLASS_NAME);
//    jmethodID   cByJava =(env)->GetStaticMethodID(mMain,"cByJava","(I)Ljava/lang/Object;");//java中有參數返回的方法的時候;必定要加上 ";" 否則會調用失敗
//    jstring result =(jstring)(env)->CallStaticObjectMethod(mMain, cByJava,1111);
    //----------------end----------------
//    return result;
//    std::string hello = "";
//    return env->NewStringUTF(hello.c_str());


//C++調用java  帶參數 無返回值
    static const char* const DL_CLASS_NAME = "com/example/android/testc/MainActivity";
    jclass  mMain = (env)->FindClass(DL_CLASS_NAME);
    jmethodID   cByJavaf =(env)->GetStaticMethodID(mMain,"cByJavaf","()V");//在方法名爲void的狀況下  V後面不能加上 ';' 否則會運行異常 報找不到方法 ()後面必定要大寫
    (env)->CallStaticVoidMethod(mMain, cByJavaf);
    jstring  js =env->NewStringUTF("ssssssss");
    return js;

}

extern "C" JNIEXPORT
jstring JNICALL NativeStr(MainActivity_testNativeFunction)(
        JNIEnv *env,
        jobject /* this */) {

    static const char* const DL_CLASS_NAME = "com/example/android/testc/MainActivity";
    jclass  mMain = (env)->FindClass(DL_CLASS_NAME);
    jmethodID   cByJavaf =(env)->GetStaticMethodID(mMain,"cByJavaf","()V");//在方法名爲void的狀況下  V後面不能加上 ';' 否則會運行異常 報找不到方法 ()後面必定要大寫
    (env)->CallStaticVoidMethod(mMain, cByJavaf);
    jstring  js =env->NewStringUTF("sssffffsssss");
    return js;

}
//C 調用Java普通方法
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_cCallJava(JNIEnv *env, jobject instance) {

// TODO C調用java

static const char* const DL_CLASS_NAME ="com/example/myapplication/MainActivity";

jclass mMain = env->FindClass(DL_CLASS_NAME);

jmethodID addMethod = env->GetMethodID(mMain,"add","()V");

env->CallVoidMethod(instance,addMethod);

return env->NewStringUTF("ffff");

}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_myapplication_MainActivity_cCallJavaParm(JNIEnv *env, jobject instance) {

static const char* const DL_CLASS_NAME ="com/example/myapplication/MainActivity";

jclass mMain = env->FindClass(DL_CLASS_NAME);

jmethodID addMethod = env->GetMethodID(mMain,"addffffff","(III)V");

env->CallVoidMethod(instance,addMethod,22,33,44);


return env->NewStringUTF("調用有參的函數");
}

  此處有個坑:  在studio3.2 中 每一個C++方法都須要加上   extern "C" JNIEXPORT 前綴  否則會提示找不到 第二個方法   NativeStr(MainActivity_testNativeFunction)

       打完收工

}
相關文章
相關標籤/搜索