JNI学习系列(二)

来源:互联网 发布:pc蛋蛋预测php源码 编辑:程序博客网 时间:2024/05/22 07:59

  在上一篇中已经介绍了关于java部分中native函数的定义和具体的调用,到目前为止还没有看到如何将java接口和JNI函数的接口关联起来。具体是如何关联起来的?Java和JNI函数之间必然存在一种联系,当调用到java层的native方法的时候映射到JNI接口。这就是下面将要介绍的JNI方法的注册,其中JNI的注册方法有两种:静态注册和动态注册。

  一、JNI方法的注册

       1、静态注册

           通过JNI函数的注册就是通过java函数名称找到对应的JNI函数,大致为如下的过程:

  • 编写native类LedNative ,然后编译成.class
  • 通过java SDK提供的javah命令,java -classpath path com.package.classname,生产JNI层的.h头文件。依据头文件声明的方法,编写对应的.c文件实现.h中声明的方法。 
     上一篇中已经编写了对象的java文件,编译之后生成了class文件。
     
   
    通过javah命令 javah -classpath .\classes\ com.led.api.LedNative在bin目录中会生成一个JNI层的.h的头文件com_led_api_LedNative.h
    [com_led_api_LedNative.h 头文件部分内容]
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h> //必须include该头文件,在该文件中声明了JNI层需要使用到方法和类型定义/* Header for class com_led_api_LedNative */#ifndef _Included_com_led_api_LedNative#define _Included_com_led_api_LedNative#ifdef __cplusplusextern "C" {#endif/* * Class:     com_led_api_LedNative * Method:    ledPowerOn * Signature: ()I */JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOn  (JNIEnv *, jclass);/* * Class:     com_led_api_LedNative * Method:    ledPowerOff * Signature: ()I */JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOff  (JNIEnv *, jclass);#ifdef __cplusplus}#endif#endif
对比java中声明的方法,ledPowerOn和ledPowerOff方法在JNI头文件中声明如下:
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOn(JNIEnv *, jclass);
JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOff(JNIEnv *, jclass);
*JNI头文件声明的规则为Java_packagename_function,其中packagename中的“.”被替换为“_”,funcation中的“_”会被替换为"_l".
当java调用ledPowerOn方法的时候,就会从对应的JNI lib文件中找对应的Java_com_led_api_LedNative_ledPowerOn,如果找到就会建立关联,后续直接通过Java_com_led_api_LedNative_ledPowerOn函数指针进行操作,具体的对应通过java虚拟机来实现。

实现对应的C文件
[com_led_api_lednative.c]
#include<stdio.h>#include"com_led_api_LedNative.h"/* * Class:     com_led_api_LedNative * Method:    ledPowerOn * Signature: ()I */JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOn  (JNIEnv *env, jclass clazz)  {  //TODO  printf("ledpoweron");  return 0;  }/* * Class:     com_led_api_LedNative * Method:    ledPowerOff * Signature: ()I */JNIEXPORT jint JNICALL Java_com_led_api_LedNative_ledPowerOff  (JNIEnv *env, jclass clazz)  {  //TODO  printf("ledpoweroff");  return 0;  }

最终编译JNI的.c和.h文件生成libLedJni.so文件,由于在开发板上运行,将生成的lib文件copy到/system/lib目录中,运行上一篇编译的APK。发现输出在JNI层的函数实现中输出的log信息“ledpoweroff”和"ledpoweron"。

对于其中JNI层函数的类型以及参数调用等都没有说明,但是到此为止整个JNI编写到JNI调用的过程都已经明了。