比較Java語言和C語言的異同,java jint_Android使用JNI實現Java與C之間傳遞數據

 2023-10-17 阅读 24 评论 0

摘要:介紹Java如何將數據傳遞給C和C回調Java的方法。? java傳遞數據給C,在C代碼中進行處理數據,處理完數據后返回給java。C的回調是Java傳遞數據給C,C需要用到Java中的某個方法,就需要調用java的方法。Android中使用JNI七個步驟:1.創建一個android工程

介紹Java如何將數據傳遞給C和C回調Java的方法。? java傳遞數據給C,在C代碼中進行處理數據,處理完數據后返回給java。C的回調是Java傳遞數據給C,C需要用到Java中的某個方法,就需要調用java的方法。

Android中使用JNI七個步驟:

1.創建一個android工程

2.JAVA代碼中寫聲明native 方法 public native String helloFromJNI();

3.用javah工具生成頭文件

比較Java語言和C語言的異同、4. 創建jni目錄,引入頭文件,根據頭文件實現c代碼

5.編寫Android.mk文件

6.Ndk編譯生成動態庫

7.Java代碼load 動態庫.調用native代碼

Java調用C進行數據傳遞

這里分別傳遞整形、字符串、數組在C中進行處理。

先學C語言還是java、聲明native 方法:

public?class?DataProvider?{

//?兩個java中的int?傳遞c?語言?,??c語言處理這個相加的邏輯,把相加的結果返回給java

public?native?int?add(int?x?,int?y);

//把一個java中的字符串傳遞給c語言,?c?語言處理下字符串,?處理完畢返回給java

public?native?String?sayHelloInC(String?s);

如何從C語言學到Java、//把一個java中int類型的數組傳遞給c語言,?c語言里面把數組的每一個元素的值?都增加5,

//然后在把處理完畢的數組,返回給java

public?native?int[]?intMethod(int[]?iNum);

}

以上方法要在C中實現的頭文件,頭文件可以理解為要在C中實現的方法

其中 JENEnv* 代表的是java環境 , 通過這個環境可以調用java的方法,jobject 表示哪個對象調用了 這個c語言的方法, thiz就表示的是當前的對象

國外java與C?/*?DO?NOT?EDIT?THIS?FILE?-?it?is?machine?generated?*/

#include?

/*?Header?for?class?cn_itcast_ndk3_DataProvider?*/

#ifndef?_Included_cn_itcast_ndk3_DataProvider

#define?_Included_cn_itcast_ndk3_DataProvider

#ifdef?__cplusplus

java類與類之間的調用。extern?"C"?{

#endif

/*

*?Class:?????cn_itcast_ndk3_DataProvider

*?Method:????add

*?Signature:?(II)I

做C的管理java團隊?*/

JNIEXPORT?jint?JNICALL?Java_cn_itcast_ndk3_DataProvider_add

(JNIEnv?*,?jobject,?jint,?jint);

/*

*?Class:?????cn_itcast_ndk3_DataProvider

*?Method:????sayHelloInC

Java值傳遞。*?Signature:?(Ljava/lang/String;)Ljava/lang/String;

*/

JNIEXPORT?jstring?JNICALL?Java_cn_itcast_ndk3_DataProvider_sayHelloInC

(JNIEnv?*,?jobject,?jstring);

/*

*?Class:?????cn_itcast_ndk3_DataProvider

javac編譯指定依賴包、*?Method:????intMethod

*?Signature:?([I)[I

*/

JNIEXPORT?jintArray?JNICALL?Java_cn_itcast_ndk3_DataProvider_intMethod

(JNIEnv?*,?jobject,?jintArray);

#ifdef?__cplusplus

為什么C語言比java難,}

#endif

#endif

C代碼出了要引用頭文件外,還要引入日志信息,以方便在C 中進行調試

//引入頭文件

#include?"cn_itcast_ndk3_DataProvider.h"

學完Java再學C語言。#include?

//導入日志頭文件

#include?

//修改日志tag中的值

#define?LOG_TAG?"logfromc"

//日志顯示的等級

java和C語言有必要都學嗎?#define?LOGD(...)?__android_log_print(ANDROID_LOG_DEBUG,?LOG_TAG,?__VA_ARGS__)

#define?LOGI(...)?__android_log_print(ANDROID_LOG_INFO,?LOG_TAG,?__VA_ARGS__)

//?java中的jstring,?轉化為c的一個字符數組

char*???Jstring2CStr(JNIEnv*???env,???jstring???jstr)

{

char*???rtn???=???NULL;

java -jar命令詳解。jclass???clsstring???=???(*env)->FindClass(env,"java/lang/String");

jstring???strencode???=???(*env)->NewStringUTF(env,"GB2312");

jmethodID???mid???=???(*env)->GetMethodID(env,clsstring,???"getBytes",???"(Ljava/lang/String;)[B");

jbyteArray???barr=???(jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode);?//?String?.getByte("GB2312");

jsize???alen???=???(*env)->GetArrayLength(env,barr);

jbyte*???ba???=???(*env)->GetByteArrayElements(env,barr,JNI_FALSE);

java -jar指定main方法、if(alen???>???0)

{

rtn???=???(char*)malloc(alen+1);?????????//new???char[alen+1];?"\0"

memcpy(rtn,ba,alen);

rtn[alen]=0;

}

C與Java哪個難?(*env)->ReleaseByteArrayElements(env,barr,ba,0);??//釋放內存

return?rtn;

}

//處理整形相加

JNIEXPORT?jint?JNICALL?Java_cn_itcast_ndk3_DataProvider_add

(JNIEnv?*?env,?jobject?obj,?jint?x,?jint?y){

JAVA調用方法,//打印?java?傳遞過來的?jstring?;

LOGI("log?from?c?code?");

LOGI("x=?%ld",x);

LOGD("y=?%ld",y);

return?x+y;

}

國二C簡單還是java簡單、//處理字符串追加

JNIEXPORT?jstring?JNICALL?Java_cn_itcast_ndk3_DataProvider_sayHelloInC

(JNIEnv?*?env,?jobject?obj,?jstring?str){

char*?p?=??Jstring2CStr(env,str);

LOGI("%s",p);

char*?newstr?=?"append?string";

//strcat(dest,?sorce)?把sorce字符串添加到dest字符串的后面

LOGI("END");

return?(*env)->NewStringUTF(env,?strcat(p,newstr));

}

//處理數組中的每一個元素

JNIEXPORT?jintArray?JNICALL?Java_cn_itcast_ndk3_DataProvider_intMethod

(JNIEnv?*?env,?jobject?obj,?jintArray?arr){

//?1.獲取到?arr的大小

int?len?=?(*env)->GetArrayLength(env,?arr);

LOGI("len=%d",?len);

if(len==0){

return?arr;

}

//取出數組中第一個元素的內存地址

jint*?p?=?(*env)->?GetIntArrayElements(env,arr,0);

int?i=0;

for(;i

LOGI("len=%ld",?*(p+i));//取出的每個元素

*(p+i)?+=?5;?//取出的每個元素加五

}

return?arr;

}

編寫Android.mk文件

LOCAL_PATH?:=?$(call?my-dir)

include?$(CLEAR_VARS)

LOCAL_MODULE????:=?Hello

LOCAL_SRC_FILES?:=?Hello.c

#增加?log?函數對應的log?庫??liblog.so??libthread_db.a

LOCAL_LDLIBS?+=?-llog

include?$(BUILD_SHARED_LIBRARY)

Java代碼load 動態庫.調用native代碼

static{

System.loadLibrary("Hello");

}

DataProvider?dp;

@Override

public?void?onCreate(Bundle?savedInstanceState)?{

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

dp?=?new?DataProvider();

}

//add對應的事件

public?void?add(View?view){

//執行C語言處理數據

int?result?=?dp.add(3,?5);

Toast.makeText(this,?"相加的結果"+?result,?1).show();

}

C中回調java方法

聲明native 方法:

public?class?DataProvider{

public?native?void?callCcode();

public?native?void?callCcode1();

public?native?void?callCcode2();

///C調用java中的空方法

public?void?helloFromJava(){

System.out.println("hello?from?java?");

}

//C調用java中的帶兩個int參數的方法

public?int?Add(int?x,int?y){

System.out.println("相加的結果為"+?(x+y));

return?x+y;

}

//C調用java中參數為string的方法

public?void?printString(String?s){

System.out.println("in?java?code?"+?s);

}

}

頭文件可以用jdk自帶的javah進行自動生成,使用javap -s可以獲取到方法的簽名。

C代碼實現回調需要三個步驟:首先要要獲取到 某個對象 , 然后獲取對象里面的方法? ,最后 調用這個方法? .

#include?"cn_itcast_ndk4_DataProvider.h"

#include?

#include?

#define?LOG_TAG?"logfromc"

#define?LOGD(...)?__android_log_print(ANDROID_LOG_DEBUG,?LOG_TAG,?__VA_ARGS__)

#define?LOGI(...)?__android_log_print(ANDROID_LOG_INFO,?LOG_TAG,?__VA_ARGS__)

//1.調用java中的無參helloFromJava方法

JNIEXPORT?void?JNICALL?Java_cn_itcast_ndk4_DataProvider_callCcode

(JNIEnv?*?env?,?jobject?obj){

//?獲取到DataProvider對象

char*?classname?=?"cn/itcast/ndk4/DataProvider";

jclass?dpclazz?=?(*env)->FindClass(env,classname);

if?(dpclazz?==?0)?{

LOGI("not?find?class!");

}?else

LOGI("find?class");

//第三個參數?和第四個參數?是方法的簽名,第三個參數是方法名??,?第四個參數是根據返回值和參數生成的

//獲取到DataProvider要調用的方法

jmethodID?methodID?=?(*env)->GetMethodID(env,dpclazz,"helloFromJava","()V");

if?(methodID?==?0)?{

LOGI("not?find?method!");

}?else

LOGI("find?method");

//調用這個方法

(*env)->CallVoidMethod(env,?obj,methodID);

}

//?2.調用java中的printString方法傳遞一個字符串

JNIEXPORT?void?JNICALL?Java_cn_itcast_ndk4_DataProvider_callCcode1

(JNIEnv?*?env,?jobject?obj){

LOGI("in?code");

//?獲取到DataProvider對象

char*?classname?=?"cn/itcast/ndk4/DataProvider";

jclass?dpclazz?=?(*env)->FindClass(env,classname);

if?(dpclazz?==?0)?{

LOGI("not?find?class!");

}?else

LOGI("find?class");

//?獲取到要調用的method

jmethodID?methodID?=?(*env)->GetMethodID(env,dpclazz,"printString","(Ljava/lang/String;)V");

if?(methodID?==?0)?{

LOGI("not?find?method!");

}?else

LOGI("find?method");

//調用這個方法

(*env)->CallVoidMethod(env,?obj,methodID,(*env)->NewStringUTF(env,"haha"));

}

//?3.?調用java中的add方法?,?傳遞兩個參數?jint?x,y

JNIEXPORT?void?JNICALL?Java_cn_itcast_ndk4_DataProvider_callCcode2

(JNIEnv?*?env,?jobject?obj){

char*?classname?=?"cn/itcast/ndk4/DataProvider";

jclass?dpclazz?=?(*env)->FindClass(env,classname);

jmethodID?methodID?=?(*env)->GetMethodID(env,dpclazz,"Add","(II)I");

(*env)->CallIntMethod(env,?obj,methodID,3l,4l);

}

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/143726.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息