一步一步學習androidNDK編程(java給c傳遞資料)

來源:互聯網
上載者:User

標籤:android   ndk   

         這篇已經是"一步一步學習androidNDK編程"的第四篇了,在這篇中,我們將會在java中傳遞代碼給c代碼。

         首先,我們建立一個android工程"ndkdata",

第一步:

同樣的首先聲明native方法,如下:

public native int add(int a,int b);public native String helloSir(String name);public native int[] intMethod(int[] intArray);
 可以看到我這裡聲明了三個方法,用來傳遞不同的資料類型給c代碼

第二步:

  由於我們的這些方法都是聲明在MainActivity.java中的,所以我們需要首先將該MainActivity.java用javac編譯為.class檔案,然後運用javah,產生對應的.h標頭檔。

  將該MainActivity.java用javac編譯為.class檔案:這個就是運行該android工程即可在bin/classes目錄下產生對應的.class檔案。

  命令列下進入bin/classes所在的目錄:執行javah com.example.ndkdata.MainActivity即可在該目錄下產生對應的com_example_ndkdata_MainActivity.h標頭檔了,內容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_example_ndkdata_MainActivity */#ifndef _Included_com_example_ndkdata_MainActivity#define _Included_com_example_ndkdata_MainActivity#ifdef __cplusplusextern "C" {#endif/* * Class:     com_example_ndkdata_MainActivity * Method:    add * Signature: (II)I */JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add  (JNIEnv *, jobject, jint, jint);/* * Class:     com_example_ndkdata_MainActivity * Method:    helloSir * Signature: (Ljava/lang/String;)Ljava/lang/String; */JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir  (JNIEnv *, jobject, jstring);/* * Class:     com_example_ndkdata_MainActivity * Method:    intMethod * Signature: ([I)[I */JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod  (JNIEnv *, jobject, jintArray);#ifdef __cplusplus}#endif#endif
      接下來我們在ndkdata工程中,建立jni目錄,然後再將剛才產生的com_example_ndkdata_MainActivity.h檔案拷貝到該目錄下,然後建立我們的c代碼:hello.c

      將com_example_ndkdata_MainActivity.h中產生的方法添加到hello.c檔案中這裡需要添加參數,因為預設產生的只有方法的參數類型,沒有參數對象,並且引入對應的標頭檔,如下:

#include<stdio.h>#include<jni.h>#include "com_example_ndkdata_MainActivity.h"JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add  (JNIEnv * env, jobject obj, jint x, jint y) {      }JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir  (JNIEnv * env, jobject obj, jstring jstr) {      }JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod  (JNIEnv * env, jobject obj, jintArray arr) {        }
接下來就是實現我們的c代碼了,如下:

#include<stdio.h>#include<jni.h>#include "com_example_ndkdata_MainActivity.h"JNIEXPORT jint JNICALL Java_com_example_ndkdata_MainActivity_add  (JNIEnv * env, jobject obj, jint x, jint y) {    return x+y;  }/** * 傳回值 char* 這個代表char數組的首地址 *  Jstring2CStr 把java中的jstring的類型轉化成一個c語言中的char 字串 */char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr){<span style="white-space:pre"></span> char*   rtn   =   NULL;<span style="white-space:pre"></span> jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String"); //String<span style="white-space:pre"></span> jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");  // 得到一個java字串 "GB2312"<span style="white-space:pre"></span> jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B"); //[ String.getBytes("gb2312");<span style="white-space:pre"></span> jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");<span style="white-space:pre"></span> jsize   alen   =   (*env)->GetArrayLength(env,barr); // byte數組的長度<span style="white-space:pre"></span> jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);<span style="white-space:pre"></span> if(alen   >   0)<span style="white-space:pre"></span> {<span style="white-space:pre"></span>  rtn   =   (char*)malloc(alen+1);         //"\0"<span style="white-space:pre"></span>  memcpy(rtn,ba,alen);<span style="white-space:pre"></span>  rtn[alen]=0;<span style="white-space:pre"></span> }<span style="white-space:pre"></span> (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //<span style="white-space:pre"></span> return rtn;}JNIEXPORT jstring JNICALL Java_com_example_ndkdata_MainActivity_helloSir  (JNIEnv * env, jobject obj, jstring jstr) {    //在c語言中 是沒有java的String<span style="white-space:pre"></span>char* cstr = Jstring2CStr(env, jstr);<span style="white-space:pre"></span>// c語言中的字串 都是以'\0' 作為結尾<span style="white-space:pre"></span>char arr[7]= {' ','h','e','l','l','o','\0'};<span style="white-space:pre"></span>strcat(cstr,arr);<span style="white-space:pre"></span>return (*env)->NewStringUTF(env,cstr);    }JNIEXPORT jintArray JNICALL Java_com_example_ndkdata_MainActivity_intMethod  (JNIEnv * env, jobject obj, jintArray arr) {    }

        編寫完了hello.c之後,需要編寫Android.mk,內容如下:

#交叉編譯編譯c/c++代碼所依賴的設定檔#擷取當前Android.mk的路徑  LOCAL_PATH := $(call my-dir)#變數初始化操作include $(CLEAR_VARS)#libhello.so 其實產生的libhello.so就是在我們這個模組的名稱前面加上lib後邊加上.soLOCAL_MODULE    := helloLOCAL_SRC_FILES := hello.cinclude $(BUILD_SHARED_LIBRARY)
      現在就需要在cygwine的命令列下進入該工程ndkdata的根目錄下,執行"ndk-build"命令產生對應的可直接啟動並執行二進位檔案,注意每次在執行"ndk-build"之後最好將android工程clean一下。

      在“ndk-build”成功之後,需要在java代碼中引入這些庫檔案:

static {        System.loadLibrary("hello");}

      注意這裡的"hello",就是我們在Android.mk檔案中寫的模組名,即LOCAL_MODULE的值。

      現在,就可以執行聲明的native方法了,在java代碼中直接調用即可,是不是很簡單呢。

源碼下載








一步一步學習androidNDK編程(java給c傳遞資料)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.