2012年6月19日 星期二

[Android] [JAVA] JNI & NDK


Java Native Interface(JNI)
JNI 是用來讓Java跟別種語言溝通的函式庫
Android中是讓Java及C之間溝通
分為Java Call C及C Call Java

Android Native Development Tools(NDK)
將C code包成.so檔,供Java利用

流程方法
藉由java撰寫native method,JNI即可在Java中呼叫C寫的程式
C的程式藉由NDK包成.so檔,就可以被JNI呼叫

//=============================================================

程式流程
1). (java) 撰寫native method,不需實做

2). 將寫好的.java檔,編成.class檔,再轉成.h檔

3). (C) 撰寫C程式碼,實做.h中的function標頭

3). 利用NDK將C程式碼轉成.so檔

4). (java) 利用JNI呼叫C的程式

//=============================================================

步驟
1). (java) 撰寫native method,不需實做
native method前要加native
要load的.so檔是libcal_bmi_c.so,扣除掉前面的lib及後面的.so

method是calbmi,回傳是double的型態
從Java傳入使用者輸入的height, weight

[Bmi.java]
package com.jni;

public class Bmi {
 public native double calbmi(double height, double weight);
 static{
  //要load的.so檔。去掉開頭的lib,及結尾的.so
  System.loadLibrary("cal_bmi_c");
 }
}

2). 將寫好的.java檔,編成.class檔,再轉成.h檔
Eclipse會自動編成.class檔
進入project的資料夾,新開jni資料夾
將編好的.h檔放在jni資料夾中
$ cd [project資料夾]

$ mkdir jni

$ cd jni

$ javah -jni -classpath [放置class的資料夾] [package].[class]

ex: javah -jni -classpath /home/qn_lo/develop/android/workspace/BmiJni/bin/classes com.jni.Bmi


3). (C) 撰寫C程式碼,實做.h中的function標頭在jni資料夾新增C程式碼檔案
將.h檔的JNIEXPORT複製到C並實作
[com_jni_Bmi.h]
/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_jni_Bmi */

#ifndef _Included_com_jni_Bmi
#define _Included_com_jni_Bmi
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_jni_Bmi
 * Method:    calbmi
 * Signature: (DD)D
 */
JNIEXPORT jdouble JNICALL Java_com_jni_Bmi_calbmi
  (JNIEnv *, jobject, jdouble, jdouble);

#ifdef __cplusplus
}
#endif
#endif


[com_jni_Bmi.c]
#include 
#include 
JNIEXPORT jdouble JNICALL Java_com_jni_Bmi_calbmi
  (JNIEnv *env, jobject obj, jdouble cheight, jdouble cweight)
{
 double height,weight,bmi;
 height=cheight/100;
 weight=cweight;
 bmi=weight/(height*height);
    return bmi;
}


4). 撰寫NDK需要的Android.mk在jni資料夾中新增Android.mk
LOCAL_MODULE是編成的.so檔名
LOCAL_SRC_FILES是要編的C程式碼檔名
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := cal_bmi_c
LOCAL_SRC_FILES := com_jni_Bmi.c

include $(BUILD_SHARED_LIBRARY)


5). 利用NDK將C程式碼轉成.so檔
 a). 先到Android NDK下載NDK
 b). 在project資料夾下新建libs的資料夾
  如果有需要,可在Eclipse中在Project按右鍵reflesh
 c). 在Eclipse的Project點右鍵[properties]
  在[Builders]中new一個編譯器,選擇program
  輸入Builder的Name,在Main標籤中,輸入Location及Working Directory


















  在Refresh標籤中,將Refresh resource upon completion勾選
  並選擇Specific resource的路徑為project的libs











  在Build Options標籤中
  勾選Specify working set of relevant resource
  並選擇Specify Resource路徑為Project的jni











 d). 按下Build All的按鈕將C編成.so檔











6). (java) 利用JNI呼叫C的程式在java要呼叫,[放JNI的class]().[native method]
new Bmi().calbmi(height, weight)



參考資料:
http://ironurbane.iteye.com/blog/425513
http://kitty.2y.idv.tw/~enijmax/linux/CLib_Jni.html

沒有留言:

張貼留言