介紹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);
}
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态