zoukankan      html  css  js  c++  java
  • 初学JNI(二)调用CC++中的方法

    布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:gravity="center">
    
        <TextView
            android:id="@+id/tv_call"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Hello World, MyActivity"
            android:padding="10dp"
            android:gravity="center" />
    
        <Button
            android:id="@+id/btn_call"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Call" />
        <Button
            android:id="@+id/btn_send_int"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="传递int参数" />
        <Button
            android:id="@+id/btn_send_str"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="传递String参数" />
        <Button
            android:id="@+id/btn_ints"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="传递int数组" />
    </LinearLayout>
    
    

    Java代码:

    public class MyActivity extends Activity implements View.OnClickListener {
    
        DataProvider mPro;
    
    
        /**
         * 使用静态代码块加载库文件
         */
        static {
            System.loadLibrary("Hello");
        }
    
        public native String helloFromJNI ();
    
        /**
         * Called when the activity is first created.
         */
        @Override
        public void onCreate (Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            mPro = new DataProvider();
    
            initView();
        }
    
        TextView mTvCall;
    
        private void initView () {
            mTvCall = (TextView) findViewById(R.id.tv_call);
            Button btnCall = (Button) findViewById(R.id.btn_call);
            Button btnInts = (Button) findViewById(R.id.btn_ints);
            Button btnInt = (Button) findViewById(R.id.btn_send_int);
            Button btnStr = (Button) findViewById(R.id.btn_send_str);
    
            btnCall.setOnClickListener(this);
            btnInt.setOnClickListener(this);
            btnInts.setOnClickListener(this);
            btnStr.setOnClickListener(this);
        }
    
        @Override
        public void onClick (View v) {
            int id = v.getId();
            switch (id) {
                case R.id.btn_call:
                    //调用CC++中的方法输出"你好 from C++."
                    mTvCall.setText(helloFromJNI());
                    Toast.makeText(MyActivity.this, helloFromJNI(), Toast.LENGTH_LONG).show();
                    break;
                case R.id.btn_send_int:
                    //向C++代码中传递两个int型参数
                    mTvCall.setText(String.valueOf(mPro.add(10, 20)));
                    break;
                case R.id.btn_send_str:
                    //向C++代码中传递一个String型参数
                    mTvCall.setText(mPro.sayHello(" JNI"));
                    break;
                case R.id.btn_ints:
                    //向C++代码中传递int数组
                    int[] arr = mPro.intMethod(new int[]{30, 40});
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < arr.length; i++) {
                        if (i == arr.length - 1)
                            sb.append(arr[i]);
                        else
                            sb.append(arr[i]).append(",");
                    }
    
                    mTvCall.setText(sb.toString());
                    break;
            }
        }
    }
    

    在定义native方法时,并不推荐直接定义在Activity中,而是专门建立一个定义native方法的类:

     */
    public class DataProvider {
    
        static{
            System.loadLibrary("Hello");
        }
    
        public native int add(int x,int y);
        public native String sayHello(String str);
        public native int[] intMethod(int[] numbers);
    }
    

    C++代码的实现:

    #include <iostream>
    #include <string>
    #include <malloc.h>
    #include <jni.h>
    #include "com_chen_jni_demo_MyActivity.h"
    #include "com_chen_jni_demo_DataProvider.h"
    using namespace std;
    
    //导入Log
    #include <android/log.h>
    #define LOG_TAG "System.out"
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    
    //jni.h没有导入的话,编译时会出现符号错误的问题
    
    //使用C++实现输出
    JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_MyActivity_helloFromJNI
      (JNIEnv * env, jobject obj){
        char* cstr = "你好 from C++.";
    
        LOGI("DEBUG %s",cstr);
        return (*env).NewStringUTF(cstr);
    }
    
    //向C++代码中传递一个String型参数
    JNIEXPORT jstring JNICALL Java_com_chen_jni_demo_DataProvider_sayHello
      (JNIEnv * env, jobject obj, jstring jstr){
    
        //声明要调用的函数
        char* jstringTostring(JNIEnv* env, jstring jstr);
        //将java字符串转换为c++中的字符数组
        char* str1=jstringTostring(env,jstr);
        char* str2="你好";
        //拼接字符数组
        strcat(str1,str2);
    
        return (*env).NewStringUTF(str1);
      }
    
    //向C++代码中传递两个int型参数
    JNIEXPORT jint JNICALL Java_com_chen_jni_demo_DataProvider_add
      (JNIEnv * env, jobject obj, jint x, jint y){
    
      return x+y;
    }
    
    //向C++代码中传递一个int数组
    JNIEXPORT jintArray JNICALL Java_com_chen_jni_demo_DataProvider_intMethod
      (JNIEnv * env,jobject obj, jintArray jintArr){
    
        //获得整型数组的长度
        jsize size = (*env).GetArrayLength(jintArr);
        //jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
        //jboolean* 表示获得数据的方式 true-1-复制 false-0-引用 c语言中
        jint* arr = (*env).GetIntArrayElements(jintArr,false);
        for(int i=0;i<size;i++){
        //第一种
            //*(arr+i) = *(arr+i)+10;
            //*(arr+i) +=10;
    
            /*
            第二种
            void (*SetIntArrayRegion)(JNIEnv*, jintArray,jsize, jsize, const jint*);
            设置IntArray中指定范围内元素的值
            参数3:范围的起始位置
            参数4:范围的擦海南过度(指定修改的元素的个数)
            参数5:const jint* 指定元素的值(地址)
            */
            int temp = *(arr+i)+10;
           (*env).SetIntArrayRegion(jintArr,i,1,&temp);
    
        }
    
        //使用的是引用方式,直接返回即可,数据已经改变
        return jintArr;
      }
      
    /**
    *将Java的String转换为char*
    */
    jstring stoJstring (JNIEnv*env, const char*pat) {
            jclass strClass = env -> FindClass("Ljava/lang/String;");
            jmethodID ctorID = env -> GetMethodID(strClass, "", "([BLjava/lang/String;)V");
            jbyteArray bytes = env -> NewByteArray(strlen(pat));
            env -> SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte *)pat); jstring encoding = env -> NewStringUTF("utf-8");
            return (jstring) env -> NewObject(strClass, ctorID, bytes, encoding);
        }
    
    //invoke function
    JNIEXPORT jstring JNICALL Java_test_cs_web_SWIFTAlianceCASmfTest_strcal (JNIEnv*env, jclass obj, jstring jstr1, jstring jstr2) {
            jbyteArray bytes = 0;
            jthrowable exc;
            char*pszResult = NULL;
            char*pszSTR1 = NULL;
            char*pszSTR2 = NULL;
            pszSTR1 = jstringTostring(env, jstr1);
            pszSTR2 = jstringTostring(env, jstr2);
            int nlen = sizeof(char)*(strlen(pszSTR1) + strlen(pszSTR2));
            pszResult = (char*)malloc(nlen);
            strcpy(pszResult, pszSTR1);
            strcat(pszResult, pszSTR2);
            jstring jstrRe = stoJstring(env, pszResult);
            free(pszSTR1);
            free(pszSTR2);
            free(pszResult);
            return (jstrRe);
        }
  • 相关阅读:
    如何实现Android重启应用程序代码 ?
    Android Intent.FLAG_NEW_TASK详解,包括其他的标记的一些解释
    WebView 和Animation冲突
    CopyOnWriteArrayList与Collections.synchronizedList的性能对比
    混淆后显示行号
    java 多线程操作List,已经做了同步synchronized,还会有ConcurrentModificationException,知道为什么吗?
    【2015年最新App Store退款流程详解】最详细AppStore退款流程图文教程
    Android 编程下 Touch 事件的分发和消费机制
    Android TouchEvent事件传递机制
    svn 规范apk的生成命名
  • 原文地址:https://www.cnblogs.com/chenchong/p/3266242.html
Copyright © 2011-2022 走看看