Android NDK编程小试---实现java和c语言的互掉
實現功能
l? 實現 java/C互相調用 android端java調用LibMain 進而執行C語言 并且傳入字符數組
l? C語言回調java Natives類的OnMessage方法打印消息,實現一個日志打印功能
l? 通過本次NDK學習,掌握NDK開發環境的配置、C語言的編譯成.so庫
Android java層代碼
Natives類:
| public class Natives { ?? /*** ?? ?* 原生庫主入口 ?? ?* @param argv ?? ?* @return ?? ?*/ ?? public static native int LibMain(String []argv); ?? /** ?? ?* C語言調用實現日志打印 ?? ?* @param text ?? ?* @param level ?? ?*/ ?? private static void OnMessage(String text,int level) ?? { ???? System.out.println("OnMessage text :"+text+" level="+level); ?? } |
該類只是聲明一個原生方法nt LibMain(String[]argv)供遠程層調用。并且一個打印消息的方法,用于遠程層調用,可以打印日志,用于原生層的調試。該類通過javah –jni com.flying.NDKTest1.Natives.java 能夠生成頭文件。
?
MainActiity類
| public class MainActivity extends Activity { ? ?? @Override ?? protected void onCreate(Bundle savedInstanceState) { ???? super.onCreate(savedInstanceState); ???? setContentView(R.layout.activity_main); ???? String argv[]={"MyLib","arg1","arg2"}; ???? try ???? { ???? Natives.LibMain(argv); ???? } ???? catch(Exception e) ???? { ??????? e.printStackTrace(); ???? } ?? } ? ?? static{ ???? System.loadLibrary("NDKTest1"); //加載.so庫 ?? } ? } |
?
原生層代碼
Natives生成的頭文件
| #include <jni.h> /* Header for class com_flying_ndktest1_Natives */ ? #ifndef _Included_com_flying_ndktest1_Natives #define _Included_com_flying_ndktest1_Natives #ifdef __cplusplus extern "C" { #endif /* ?* Class:???? com_flying_ndktest1_Natives ?* Method:??? LibMain ?* Signature: ([Ljava/lang/String;)I ?*/ JNIEXPORT jint JNICALL Java_com_flying_ndktest1_Natives_LibMain ? (JNIEnv *, jclass, jobjectArray); ? #ifdef __cplusplus } #endif #endif |
?
Lib.c
| #include "com_flying_ndktest1_Natives.h" #include <stdio.h> #include <stdlib.h> #define CB_CLASS "com_flying_ndktest1_Natives" ? /** ?* OnMessage 回調方法 ?*/ #define CB_CLASS_CB "OnMessage" #define CB_CLASS_MSG_SIG "(Ljava/lang/String;I)v" ? ? int lib_main(int argc ,char **argv); ? const int getArrayLen(JNIEnv *env,jobjectArray jarray); ? void jni_printf(char *format,...); ? static JavaVM *g_VM; ? static jclass jNativesCls; ? /* ?* Class:???? com_flying_ndktest1_Natives ?* Method:??? LibMain ?* Signature: ([Ljava/lang/String;)I ?*/ JNIEXPORT jint JNICALL Java_com_flying_ndktest1_Natives_LibMain ? (JNIEnv * env, jclass class, jobjectArray jargv) ???????? { ?????????????????? (*env)->GetJavaVM(env,&g_VM); ? ?????????????????? jsize clen=getArrayLen(env,jargv); ? ?????????????????? char *args[(int)clen]; ? ?????????????????? int i; ?????????????????? jstring jrow; ? ?????????????????? for(i=0;i<clen;i++) ?????????????????? { ??????????????????????????? jrow=(jstring)(*env)->GetObjectArrayElement(env,jargv,i); ??????????????????????????? const char *row=(*env)->GetStringUTFChars(env,jrow,0); ? ??????????????????????????? args[i]=malloc(strlen(row)+1); ??????????????????????????? strcpy(args[i],row); ? ??????????????????????????? jni_printf("Main argv[%d]=%s",i,args[i]);? //打印args參數對應的字符串 ? ??????????????????????????? (*env)->ReleaseStringUTFChars(env,jrow,row); //釋放java字符串jrow ? ?????????????????? } ? ?????????????????? //加載com_flying_ndktest1_Natives類 ? ?????????????????? jNativesCls=(*env)->FindClass(env,CB_CLASS); ?????????????????? if(jNativesCls==0) ?????????????????? { ??????????????????????????? jni_printf("Unable to find class %s",CB_CLASS); ??????????????????????????? return -1; ?????????????????? } ?????????????????? lib_main(clen,args); ?????????????????? return 0; ? ???????? } ???????? /** ???????? ?* 向java層返回一個字符串 ???????? ?*/ ???????? jmethodID mSendStr; ???????? static void jni_send_str(const char *text,int level) ???????? { ?????????????????? JNIEnv *env; ?????????????????? if(!g_VM) ?????????????????? { ??????????????????????????? printf("I_JNI_NOVM:%s\n",text); ??????????????????????????? return ; ?????????????????? } ?????????????????? (*g_VM)->AttachCurrentThread(g_VM,(void **)&env,NULL); ?????????????????? if(!jNativesCls) ?????????????????? { ??????????????????????????? jNativesCls=(*env)->FindClass(env,CB_CLASS); ??????????????????????????? if(jNativesCls==0) ??????????????????????????? { ???????????????????????????????????? printf("Unable to find class %s\n",CB_CLASS); ???????????????????????????????????? return ; ??????????????????????????? } ?????????????????? } ?????????????????? if(!mSendStr) ?????????????????? { ?????????????????? ???????? mSendStr=(*env)->GetStaticMethodID(env,jNativesCls,CB_CLASS_CB,CB_CLASS_MSG_SIG); ? ?????????????????? } ?????????????????? if(mSendStr) ?????????????????? { ?????????????????? ???????? (*env)->CallStaticVoidMethod(env,jNativesCls,mSendStr,(*env)->NewStringUTF(env,text),(jint) level); ? ?????????????????? }else ?????????????????? { ??????????????????????????? printf("Unable to find method :%s,signature :%s \n",CB_CLASS_CB,CB_CLASS_MSG_SIG); ? ?????????????????? } ???????? } ? ???????? void jni_printf(char *format,...) ???????? { ?????????????????? va_list argptr; ?????????????????? static char string[1024]; ?????????????????? va_start(argptr,format); ?????????????????? vsprintf(string,format,argptr); ?????????????????? va_end(argptr); ?????????????????? jni_send_str(string,0); ???????? } ? ???????? const int getArrayLen(JNIEnv *env,jobjectArray jarray) ???????? { ?????????????????? return (*env)->GetArrayLength(env,jarray); ???????? } ? ???????? int lib_main(int argc,char **argv) ???????? { ?????????????????? int i; ?????????????????? jni_printf("Enteing LIB MAIN"); ?????????????????? for(i=0;i<argc;i++) ?????????????????? { ??????????????????????????? jni_printf("LIB MAIN argv[%d]=%s",i,argv[i]); ?????????????????? } ?????????????????? return 0; ???????? } 至此,完成了java c語言的互掉,最主要的是實現了原生層日志打印的功能,這個功能可以為今后開發提供輕量級的日志調試功能!! |
?
?
總結
以上是生活随笔為你收集整理的Android NDK编程小试---实现java和c语言的互掉的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GPU 内存的分级综述(gpu memo
- 下一篇: 解决AndroidManifest.xm