热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入探索NDK与JNI技术的实践应用与学习路径

本文深入探讨了NDK与JNI技术在实际项目中的应用及其学习路径。通过分析工程目录结构和关键代码示例,详细介绍了如何在Android开发中高效利用NDK和JNI,实现高性能计算和跨平台功能。同时,文章还提供了从基础概念到高级实践的系统学习指南,帮助开发者快速掌握这些关键技术。

工程的目录结构如下:


public class MainActivity extends Activity {/** Called when the activity is first created. */@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);String[] argv=new String[]{"mylib","Gao","GaoMatrix"};Natives.libMain(argv);}
}

/*** @author GaoMatrix E-mail:gcquan08@gmail.com* @version Time:2011-8-20*/
public class Natives {static{System.loadLibrary("mylib");}public static native int libMain(String[] argv);private static void onMessage(String text,int level){// System.out.println("Message:"+text+" Level:"+level);Log.d("JNI", "Message:"+text+" Level:"+level);}
}

Android.mk:

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:=mylib
LOCAL_SRC_FILES:=mylib.c
LOCAL_LDLIBS := -llog
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -lloginclude $(BUILD_SHARED_LIBRARY)

include/Natives.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class Natives */#ifndef _Included_Natives
#define _Included_Natives
#ifdef __cplusplus
extern "C" {
#endif
/** Class: Natives* Method: libMain* Signature: ([Ljava/lang/String;)I*/
JNIEXPORT jint JNICALL Java_com_gao_Natives_libMain(JNIEnv *, jclass, jobjectArray);#ifdef __cplusplus
}
#endif
#endif
mylib.c:

#include
#include
#include
#include "include/Natives.h"#include
#define LOG_TAG "JNI"
#define LOGD(a) __android_log_write(ANDROID_LOG_DEBUG,LOG_TAG,a)#define CB_CLASS "com/gao/Natives"/**
* onMessage callback
*/
#define CB_CLASS_MSG_CB "onMessage"
#define CB_CLASS_MSG_SIG "(Ljava/lang/String;I)V"//lib main sub
int lib_main(int argc,char **argv);//Used to get the len of a java Array
const int getArrayLen(JNIEnv* env,jobjectArray jarray);//print str message back to java
void jni_printf(char* format,...);//Global env ref(for callback)
static JavaVM* g_VM;//Global Reference to the native java calss com.gao.Natives.java
static jclass jNativesCls;JNIEXPORT jint JNICALL Java_com_gao_Natives_libMain(JNIEnv *env, jclass cls, jobjectArray jarray)
{//obtain a global ref to the caller class(*env)->GetJavaVM(env,&g_VM);//Extract char **args from java arrayjsize len=getArrayLen(env,jarray);char* args[(int)len];int i;jstring jrow;for(i=0;iGetObjectArrayElement(env,jarray,i);const char* row=(*env)->GetStringUTFChars(env,jrow,0);args[i]=malloc(strlen(row)+1);strcpy(args[i],row);//print argsjni_printf("Main argv[%d]=%s",i,args[i]);//LOGD("From C "+*args[i]);LOGD("From C ");//free java string jrow(*env)->ReleaseStringUTFChars(env,jrow,row);}//Load the com.gao.Natives classjNativesCls=(*env)->FindClass(env,CB_CLASS);if(jNativesCls==0){jni_printf("Unable to find class:%s",CB_CLASS);return -1;}//Invoke the lib main sub.This will loop forener//Program agrs com from Javalib_main(len,args);return 0;
}/**
*Send a string back to 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);//Load jni.Natives if missingif(!jNativesCls){jNativesCls=(*env)->FindClass(env,CB_CLASS);if(jNativesCls==0){printf("Unable to find class:%s",CB_CLASS);return;}}//Call com.gao.Natives.onMessage(String,int)if(!mSendStr){//Get a ref to the static method:com.gao.Natives.onMessagemSendStr=(*env)->GetStaticMethodID(env,jNativesCls,CB_CLASS_MSG_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_MSG_CB, CB_CLASS_MSG_SIG );}}/**
*Get java array length
*/const int getArrayLen(JNIEnv* env,jobjectArray jarray)
{return (*env)->GetArrayLength(env,jarray);
}/*** Printf into the java layer* does a varargs printf into a temp buffer* and calls jni_sebd_str*/
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);
}/**
*Library main sub
*/
int lib_main(int argc,char** argv)
{int i;jni_printf("Entering LIB MAIN");for(i=0;i}
运行结果:

08-20 21:50:50.350: DEBUG/JNI(7574): Message:Main argv[0]=mylib Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): From C
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Main argv[1]=Gao Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): From C
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Main argv[2]=GaoMatrix Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): From C
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Entering LIB MAIN Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Lib Main argv[0]=mylib Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Lib Main argv[1]=Gao Level:0
08-20 21:50:50.350: DEBUG/JNI(7574): Message:Lib Main argv[2]=GaoMatrix Level:0


推荐阅读
  • 深入解析Android中的SQLite数据库使用
    本文详细介绍了如何在Android应用中使用SQLite数据库进行数据存储。通过自定义类继承SQLiteOpenHelper,实现数据库的创建与版本管理,并提供了具体的学生信息管理示例代码。 ... [详细]
  • Qt QTableView 内嵌控件的实现方法
    本文详细介绍了在 Qt QTableView 中嵌入控件的多种方法,包括使用 QItemDelegate、setIndexWidget 和 setIndexWidget 结合布局管理器。每种方法都有其适用场景和优缺点。 ... [详细]
  • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
  • 深入解析Spring启动过程
    本文详细介绍了Spring框架的启动流程,帮助开发者理解其内部机制。通过具体示例和代码片段,解释了Bean定义、工厂类、读取器以及条件评估等关键概念,使读者能够更全面地掌握Spring的初始化过程。 ... [详细]
  • 本文介绍了在Android项目中实现时间轴效果的方法,通过自定义ListView的Item布局和适配器逻辑,实现了动态显示和隐藏时间标签的功能。文中详细描述了布局文件、适配器代码以及时间格式化工具类的具体实现。 ... [详细]
  • Nginx 反向代理与负载均衡实验
    本实验旨在通过配置 Nginx 实现反向代理和负载均衡,确保从北京本地代理服务器访问上海的 Web 服务器时,能够依次显示红、黄、绿三种颜色页面以验证负载均衡效果。 ... [详细]
  • 在 Android 开发中,通过 Intent 启动 Activity 或 Service 时,可以使用 putExtra 方法传递数据。接收方可以通过 getIntent().getExtras() 获取这些数据。本文将介绍如何使用 RoboGuice 框架简化这一过程,特别是 @InjectExtra 注解的使用。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 在编译BSP包过程中,遇到了一个与 'gets' 函数相关的编译错误。该问题通常发生在较新的编译环境中,由于 'gets' 函数已被弃用并视为安全漏洞。本文将详细介绍如何通过修改源代码和配置文件来解决这一问题。 ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 本文将详细探讨 Java 中提供的不可变集合(如 `Collections.unmodifiableXXX`)和同步集合(如 `Collections.synchronizedXXX`)的实现原理及使用方法,帮助开发者更好地理解和应用这些工具。 ... [详细]
  • 软件工程课堂测试2
    要做一个简单的保存网页界面,首先用jsp写出保存界面,本次界面比较简单,首先是三个提示语,后面是三个输入框,然 ... [详细]
  • java文本编辑器,java文本编辑器设计思路
    java文本编辑器,java文本编辑器设计思路 ... [详细]
  • 本文介绍如何在Windows Forms应用程序中使用C#实现DataGridView的多列排序功能,包括升序和降序排序。 ... [详细]
author-avatar
大叔丶你好哇塞
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有