zoukankan      html  css  js  c++  java
  • C++ Android 通过JNI 双向调用注意事项

    在一般的APP项目中,都不用用到C++  所以当我们需要使用C++(也就是JNI)的时候 需要在 Android studio 中进行如下设置

    (这里需要特别注意下  如果你的 Android studio版本是3.0及以上时,那么原来3.0以下的版本 在运行项目时会提示 “No toolchains found in the NDK toolchains folder for ABI with prefix: arm-linux-androideabi” 

    我的解决方法是  在3.0以下的版本点击安装 CMAKE,NDK,3.0以上的项目也没有报错)

    补充:https://developer.android.google.cn/ndk/downloads/  下载替换 自己sdk 中 toolchains 文件夹,及android-ndk-r16b-windows-x86_64android-ndk-r16b oolchains 中的文件就可以解决上面的问题

    方法有两种:

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

    (2)ctrl+alt+S -->搜索框中 输入 SDK -->勾选CMAKE,NDK

     如下图:

    配置做完后 在撸代码之前 我们来对 java类型与C++类型的比较

    /*
        *
        *
           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++ 就可以

    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)

           打完收工

    }
  • 相关阅读:
    算法导论--第七章、快速排序
    PS操作
    【字符编码】彻底理解字符编码
    HTML网页设计-代码效果记录
    Ubuntu 18.04 nvidia driver 390.48 安装 TensorFlow 1.12.0 和 PyTorch 1.0.0 详细教程
    cmake更新版本简记
    计算机图形学(二)——微表面模型
    计算机图形学(一)——辐照度学概述
    蒙特卡洛积分与重要性采样详解
    for循环提高内存访问效率的做法
  • 原文地址:https://www.cnblogs.com/LKit/p/9797170.html
Copyright © 2011-2022 走看看