JNI文件的创建方法

通常,JNI文件有两种创建方法:

1. 采用javah工具自动生成相应的JNI头文件,再实现相应的函数,如:

使用Java编写HelloWorld Android应用程序:

复制代码
package com.lucyfyr;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;

public class HelloWorld extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Log.v("dufresne", printJNI("I am HelloWorld Activity"));
}
  static
  {
    //加载库文件
    System.loadLibrary("HelloWorldJni");
  }
   //声明原生函数 参数为String类型 返回类型为String
  private native String printJNI(String inputStr);
}

生成共享库的头文件:

  进入到eclipse生成的Android Project中 :/HelloWorld/bin/classes/com/lucyfyr/ 下:

  可以看到里面后很多后缀为.class的文件,就是eclipse为我们自动编译好了的java文件,其中就有:

    HelloWorld.class文件。

  退回到classes一级目录:/HelloWorld/bin/classes/

执行如下命令:

  javah com.lucyfyr.HelloWorld

  生成文件:com_lucyfyr_HelloWorld.h

 

复制代码
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_lucyfyr_HelloWorld */
#ifndef _Included_com_lucyfyr_HelloWorld
#define _Included_com_lucyfyr_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_lucyfyr_HelloWorld
* Method: printJNI
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
复制代码

 

可以看到自动生成对应的函数:Java_com_lucyfyr_HelloWorld_printJNI

    Java_ + 包名(com.lucyfyr) 类名(HelloWorld) + 接口名(printJNI):必须要按此JNI规范来操作;

  java虚拟机就可以在com.simon.HelloWorld类调用printJNI接口的时候自动找到这个C实现的Native函数调用。

  当然函数名太长,可以在.c文件中通过函数名映射表来实现简化。


实现JNI原生函数源文件:

新建com_lucyfyr_HelloWorld.c文件:

 

复制代码
#include <jni.h>
#define LOG_TAG "HelloWorld"
#include <utils/Log.h>
/* Native interface, it will be call in java code */
JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI(JNIEnv *env, jobject obj,jstring inputStr)
{
  LOGI("dufresne Hello World From libhelloworld.so!");
  // 从 instring 字符串取得指向字符串 UTF 编码的指针
  const char *str =
  (const char *)(*env)->GetStringUTFChars( env,inputStr, JNI_FALSE );
  LOGI("dufresne--->%s",(const char *)str);
  // 通知虚拟机本地代码不再需要通过 str 访问 Java 字符串。
  (*env)->ReleaseStringUTFChars(env, inputStr, (const char *)str );
  return (*env)->NewStringUTF(env, "Hello World! I am Native interface");
}
/* This function will be call when the library first be load. * You can do some init in the libray. return which version jni it support. */ jint JNI_OnLoad(JavaVM* vm, void* reserved) {   void *venv;   LOGI("dufresne----->JNI_OnLoad!");   if ((*vm)->GetEnv(vm, (void**)&venv, JNI_VERSION_1_4) != JNI_OK) {     LOGE("dufresne--->ERROR: GetEnv failed");     return -1;   }
  return JNI_VERSION_1_4; }


2. 手工编写,采用registerNativeMethods函数来注册本地函数,如:


定义如下的class
public class DVB {
static {
try{
System.loadLibrary("DVBjni");
}catch(UnsatisfiedLinkError ule) {
System.err.println("WARNING: Could not load library!");
}
}
private static native final void native_init();
}

相应的JNI文件可以这样编写:

static void android_com_konka_dvb_DVB_native_init(JNIEnv *env)
{
}


static JNINativeMethod gMethods[] = {
{"native_init",                 "()V",                        (void *)android_com_konka_dvb_DVB_native_init}
};


static int register_android_com_konka_dvb_DVB(JNIEnv *env)
{
    ALOGV("register_android_com_konka_dvb_DVB was called");
    return AndroidRuntime::registerNativeMethods(env,
                "android/com/konka/dvb/DVB", gMethods, NELEM(gMethods));
}


jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1;


ALOGV("JNI_OnLoad was called");


if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE("ERROR: GetEnv failed\n");
goto bail;
}

assert(env != NULL);

if (register_android_com_konka_dvb_DVB(env) < 0) {
ALOGE("ERROR: DVB native registration failed\n");
goto bail;
}

/* success -- return valid version number */
result = JNI_VERSION_1_4;

bail:
return result;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值