Andoird 中使用了一种不同传统Java JNI的方式来定义其native的函数。其中很重要的区别是Andorid使用了一种Java 和 C 函数的映射表数组,并在其中描述了函数的参数和返回值。这个数组的类型是JNINativeMethod,定义如下:

typedef struct {

const char* name;

const char* signature;

void* fnPtr;

} JNINativeMethod;

第一个变量name是Java中函数的名字。

第二个变量signature,用字符串是描述了函数的参数和返回值

第三个变量fnPtr是函数指针,指向C函数。

其中比较难以理解的是第二个参数,例如

"()V"

"(II)V"

"(Ljava/lang/String;Ljava/lang/String;)V"

实际上这些字符是与函数的参数类型一一对应的。

"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();

"(II)V" 表示 void Func(int, int);

具体的每一个字符的对应关系如下

字符 Java类型 C类型

V      void            void

Z       jboolean     boolean

I        jint              int

J       jlong            long

D      jdouble       double

F      jfloat            float

B      jbyte            byte

C      jchar           char

S      jshort          short

数组则以"["开始,用两个字符表示

[I       jintArray      int[]

[F     jfloatArray    float[]

[B     jbyteArray    byte[]

[C    jcharArray    char[]

[S    jshortArray   short[]

[D    jdoubleArray double[]

[J     jlongArray     long[]

[Z    jbooleanArray boolean[]

上面的都是基本类型。如果Java函数的参数是class,则以"L"开头,以";"结尾中间是用"/" 隔开的包及类名。而其对应的C函数名的参数则为jobject. 一个例外是String类,其对应的类为jstring

Ljava/lang/String; String jstring

Ljava/net/Socket; Socket jobject

如果JAVA函数位于一个嵌入类,则用$作为类名间的分隔符。

例如 "(Ljava/lang/String;Landroid/os/FileUtils$FileStatus;)Z"

下边是我在做串口通信时的代码:

  1. static const char *classPathName = "android/serialport/SerialPort";
  2. //注意Ljava/io/FileDescriptor;最后的分号,刚开始做时漏了这个分号,查了两天时间,汗
  3. static JNINativeMethod methods[] = {
  4. {"open", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)android_serialport_SerialPort_open },
  5. {"close", "()V", (void*)android_serialport_SerialPort_close },
  6. };
  7. /*
  8. * Register several native methods for one class.
  9. */
  10. static int registerNativeMethods(JNIEnv* env, const char* className,
  11. JNINativeMethod* gMethods, int numMethods)
  12. {
  13. jclass clazz;
  14. clazz = (*env)->FindClass(env, className);
  15. if (clazz == NULL)
  16. return JNI_FALSE;
  17. if ((*env)->RegisterNatives(env, clazz, gMethods, numMethods) < 0)
  18. {
  19. LOGE("register nativers error");
  20. return JNI_FALSE;
  21. }
  22. return JNI_TRUE;
  23. }
  24. /*
  25. * Register native methods for all classes we know about.
  26. *
  27. * returns JNI_TRUE on success.
  28. */
  29. static int registerNatives(JNIEnv* env)
  30. {
  31. if (!registerNativeMethods(env, classPathName,
  32. methods, sizeof(methods) / sizeof(methods[0]))) {
  33. return JNI_FALSE;
  34. }
  35. return JNI_TRUE;
  36. }
  37. /*
  38. * This is called by the VM when the shared library is first loaded.
  39. */
  40. jint JNI_OnLoad(JavaVM* vm, void* reserved)
  41. {
  42. JNIEnv* env = NULL;
  43. jint result = -1;
  44. LOGI("Entering JNI_OnLoad\n");
  45. if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_4) != JNI_OK)
  46. goto bail;
  47. assert(env != NULL);
  48. if (!registerNatives(env))
  49. goto bail;
  50. /* success -- return valid version number */
  51. result = JNI_VERSION_1_4;
  52. bail:
  53. LOGI("Leaving JNI_OnLoad (result=0x%x)\n", result);
  54. return result;
  55. }

android_serialport_SeriaPort_open的函数原型为:

static jobject android_serialport_SerialPort_open(JNIEnv *env, jobject thiz, jstring path, jint baudrate);

static void android_serialport_SerialPort_close(JNIEnv *env, jobject thiz);

另外还要注意一点,如果是C++,使用的是env, 如果是C,使用的是(*env),最好参考相应系统中的代码来写。

Android JNI 使用的数据结构JNINativeMethod详解的更多相关文章

  1. Android安卓书籍推荐《Android驱动开发与移植实战详解》下载

    百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与 ...

  2. Android EventBus 3.0 实例使用详解

    EventBus的使用和原理在网上有很多的博客了,其中泓洋大哥和启舰写的非常非常棒,我也是跟着他们的博客学会的EventBus,因为是第一次接触并使用EventBus,所以我写的更多是如何使用,源码解 ...

  3. Android开发:文本控件详解——TextView(一)基本属性

    一.简单实例: 新建的Android项目初始自带的Hello World!其实就是一个TextView. 在activity_main.xml中可以新建TextView,从左侧组件里拖拽到右侧预览界面 ...

  4. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

  5. Android 应用程序之间内容分享详解(二)

    转载请注明出处:http://blog.csdn.net/xiaanming/article/details/9428613 Android 应用程序之间内容分享详解(一) 之前给大家分享了你开发的应 ...

  6. Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

    [Android布局学习系列]   1.Android 布局学习之——Layout(布局)详解一   2.Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)   3.And ...

  7. Android 多线程之IntentService 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  8. Android 多线程之HandlerThread 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  9. Android 6.0 RK3288 ROM编译详解+命令详解【转】

    本文转载自:http://blog.csdn.net/MLQ8087/article/details/58607692 Android 6.0 RK3288 ROM编译详解+命令详解 原创 2017年 ...

随机推荐

  1. Apache shiro集群实现 (八) web集群时session同步的3种方法

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  2. Dynamics CRM2016 升级老版本报“JavaScript Web 资源包含对 Microsoft Dynamics CRM 4.0 (2007) Web 服务终结点的引用”问题的解决办法

    今天在新的服务器上部署了CRM2016 on-premises,并将CRM2015的数据库拷贝过来准备附加后升级,但在升级过程中遇到了如下错误,向导检测到了我的JavaScript Web 资源中包含 ...

  3. Spark Scheduler模块源码分析之TaskScheduler和SchedulerBackend

    本文是Scheduler模块源码分析的第二篇,第一篇Spark Scheduler模块源码分析之DAGScheduler主要分析了DAGScheduler.本文接下来结合Spark-1.6.0的源码继 ...

  4. Android简易实战教程--第三十三话《 AsyncTask异步倒计时》

    本篇小案例,完成一个倒计时.方式选择AsyncTask.代码贴在下面: 布局文件soeasy: <LinearLayout xmlns:android="http://schemas. ...

  5. 代码优化>>>Android ListView适配器三级优化详解

    转载本专栏每一篇博客请注明转载出处地址,尊重原创.此博客转载链接地址:点击打开链接  http://blog.csdn.net/qq_32059827/article/details/52718489 ...

  6. FFmpeg的HEVC解码器源代码简单分析:解码器主干部分

    ===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...

  7. introduction of velocity

    一.velocity 简介 基于java 的模板引擎,apache 旗下的开源软件项目. 目的在于隔离 表示层和业务逻辑层,当然现在做的不仅仅是这些. 二.应用场景 web 应用程序:创建html页面 ...

  8. iOS7 CookBook精彩瞬间(三)UIActivityViewController的基本使用及自定义Activity

    1.基本使用 UIActivityViewController主要用于分享内容,创建activityView的方法很简单,调用下面的方法创建: [[UIActivityViewController a ...

  9. 【移动开发】Context类bindService()参数

    bindService()是Context的一个方法,它是抽象的.函数原型的代码如下:(android 2.3.3) /** * Connect to an application service, ...

  10. 百度地图隐藏缩放控件比例尺Logo

    对于百度地图最新版V3.7.3,以前的隐藏控件方法失效,可用以下方法隐藏: 1.隐藏缩放控件: mMapView.showZoomControls(false); 2.隐藏比例尺: mMapView. ...