Linux下eclipse中通過(guò)jni調(diào)用.so實(shí)例

系統(tǒng)環(huán)境:64位Ubuntu14.04、eclipse 5.3版本,jdk1.8版本,vim編譯器

1、本實(shí)例是java代碼通過(guò)jni調(diào)用c/c++語(yǔ)言生成的.so庫(kù),本庫(kù)提供兩個(gè)方法,當(dāng)調(diào)用讀目錄方法,并輸入一個(gè)目錄的路徑時(shí),會(huì)打印出輸入目錄下的所有文件,當(dāng)調(diào)用,讀文件方法,并輸入一個(gè)目錄文件的路徑會(huì)讀取本文件的前五個(gè)字節(jié),并創(chuàng)建一個(gè)和輸入文件名相同后綴添加一個(gè).new的文件,然后將讀取的五個(gè)字節(jié)寫(xiě)入到本文件中。

2、在eclipse中創(chuàng)建一個(gè)類(lèi),流程如下File->New->Java Project->在Projectname框中寫(xiě)入項(xiàng)目名稱(chēng)->點(diǎn)擊finish。右擊右側(cè)欄的項(xiàng)目中的src選擇new->Package->在name中輸入demo(這是java中的包名)->Finish,然后右擊src下的demo->new->class->在name框中輸入MainClass(這個(gè)是類(lèi)名)。

3、在類(lèi)中寫(xiě)如下代碼

Java代碼

package demo;
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
public classMainClass {
  static
  {
    //在linux中可使用這個(gè)函數(shù)然后直接寫(xiě)so的絕對(duì)路徑加載so文件
    System.load("/home/native/read_dir_file/libTestReadFile.so");
  }
  //在MainClass類(lèi)中定義了一個(gè)String結(jié)構(gòu)體
  public String message = null;
  public native void callCppFunction();
  public native void read_dir();
  public native void read_file();
  public static void main(String [] args) throwsIOException
  {
    BufferedReader reader = newBufferedReader(newInputStreamReader(System.in));
    String str = reader.readLine();
    MainClass obj = new MainClass();
    obj.message = str;
    //obj.callCppFunction();
    //obj.read_dir();//讀取目錄的方法
    obj. read_file();//讀取文件的方法
    System.out.println("Javaoutput:" + obj.message);
  }
}

4、進(jìn)入java所在的目錄src/demo/目錄下執(zhí)行javac MainClass.java(這個(gè)是剛剛寫(xiě)的java文件),生成一個(gè)MainClass.class文件 進(jìn)入bin的上一層目錄然后進(jìn)入bin目錄下,執(zhí)行javah demo.MaicClass這時(shí)候在當(dāng)前目錄下生成一個(gè)MainClass.h文件,把這文件拷貝到寫(xiě)c的目錄下。
頭文件內(nèi)容如下
Java代碼,c的頭文件相同
MainClass.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for classdemo_MainClass */
#ifndef_Included_demo_MainClass
#define_Included_demo_MainClass
#ifdef __cplusplus
extern "C"{
  #endif
  /*
  * Class:demo_MainClass
  * Method:callCppFunction
  * Signature: ()V
  */
  JNIEXPORT void JNICALL Java_demo_MainClass_callCppFunction
  (JNIEnv *, jobject);
  /*
  * Class:demo_MainClass
  * Method:read_dir
  * Signature: ()V
  */
  JNIEXPORT void JNICALL Java_demo_MainClass_read_1dir
  (JNIEnv *, jobject);//注意這里它會(huì)自動(dòng)添加一個(gè)數(shù)字1
  /*
  * Class:demo_MainClass
  * Method:read_file
  * Signature: ()V
  */
  JNIEXPORT void JNICALL Java_demo_MainClass_read_1file
  (JNIEnv *, jobject);
  #ifdef __cplusplus
}
#endif
#endif

5、在和.h同一目錄下,創(chuàng)建一個(gè)MainClass.c文件文件內(nèi)容如下
MainClass.c內(nèi)容如下:
cpp代碼

#include"demo_MainClass.h"
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types/h>
#include <string.h>
//讀取目錄函數(shù)
int cont = 0;
intdir_file_num(char * dirname)
{
  printf("%sdir:\n", dirname);
  DIR *dirp = opendir(dirname);//打開(kāi)目錄
  if(dirp == NULL)
  {
    perror("open dir err");
    return -1;
  }
  struct dirent * dentp = NULL;
  //讀取目錄中所用文件
  while((dentp = readdir(dirp)))
  {
        if(dentp->d_type == DT_REG)
        {
            printf("%s\n",dentp->d_name);
            cont++;
        }
        if(dentp->d_type == DT_DIR)
        {
            if((strcmp(".",dentp->d_name)) ==0 || (strcmp("..", dentp->d_name)) == 0)
            {
                continue;
            }
            char new_dir_name[256] = {0};
            sprintf(new_dir_name,"%s/%s",dirname, dentp->d_name);//directoryfull path
            dir_file_num(new_dir_name);
        }
    }
  return cont;
}

//讀取文件前5個(gè)字節(jié)
intread_file_info(char *filename)
{
    if(NULL == filename)
    {
        return -1;
    }
    printf("%s", filename);
    FILE *fd;
    size_t i = 0;
    char buf[24] = {0};
    charnew_file_name[256]={0};
    sprintf(new_file_name, "%s.new",filename);
    //讀取文件前五個(gè)字
    if(!(fd = fopen(filename, "r")))
    {
        return -2;
    }
    i = fread(buf, 1, 5, fd);
    if( i < 5)
    {
        printf("文件讀取失敗!\n");
        return -3;
    }
    fclose(fd);
    fd = fopen(new_file_name, "w");
    if(fd == NULL)
    {
        printf("文件打開(kāi)失敗");
        return -4;
    }
        i = fwrite(buf, 1, 5, fd);
        if(i == 0)
        {
            printf("文件寫(xiě)入失敗\n");
            return -5;
        }
    fclose(fd);
    return 0;
}

JNIEXPORT void
JNICALLJava_demo_MainClass_callCppFunction(JNIEnv *env, jobject obj)
{

    jclass clazz;
    jfieldID fid;
    jstring j_str;
    jstring j_newStr;
    const char *c_str = NULL;
    //獲取MainClass類(lèi)的Class引用
    clazz = (*env)->GetObjectClass(env, obj);
    if(NULL == clazz)
    {
        return;
    }
    
    //獲取MainClass類(lèi)實(shí)例變量message的屬性ID
    fid = (*env)->GetFieldID(env, clazz,"message", "Ljava/lang/String;");
    if(fid < 0)
    {
        return;
    }
    
    //獲取實(shí)例message的值
    j_str = (jstring)(*env)->GetObjectField(env,obj, fid);
    if(NULL == j_str)
    {
        return;
    }
    
    //將Unicode編碼的java字符串轉(zhuǎn)換為c風(fēng)格的字符串
    c_str = (*env)->GetStringUTFChars(env,j_str, NULL);
    if(NULL == c_str)
    {
        return;
    }

    int i = 0;
    //調(diào)用顯示目錄下文件的函數(shù)
    i = dir_file_num((char *)c_str);
    if(i < 0)
    {
        printf("dir_file_num err!\n");
        return;
    }
}

//打印目錄下所用文件
JNIEXPORT void
JNICALLJava_demo_MainClass_read_1dir(JNIEnv *env, jobject obj)
{
    jclass clazz;
    jfieldID fid;
    jstring j_str;
    jstring j_newStr;
    const char *c_str = NULL;
    
    //獲取MainClass類(lèi)的Class引用
    clazz = (*env)->GetObjectClass(env, obj);
    if(NULL == clazz)
    {
        return;
    }

    //獲取MainClass類(lèi)實(shí)例變量message的屬性ID
    fid =(*env)->GetFieldID(env, clazz, "message","Ljava/lang/String;");
    if(fid < 0)
    {
        return;
    }

    //獲取實(shí)例message的值
    j_str =(jstring)(*env)->GetObjectField(env, obj, fid);
    if(NULL == j_str)
    {
        return;
    }

    //將Unicode編碼的java字符串轉(zhuǎn)換為c風(fēng)格的字符串
    c_str = (*env)->GetStringUTFChars(env,j_str, NULL);
    if(NULL == c_str)
    {
        return;
    }

    int i = 0;
    //調(diào)用顯示目錄下文件的函數(shù)
    i = dir_file_num((char*)c_str);
    if(i < 0)
    {
        printf("dir_file_numerr!\n");
        return;
    }

}


//讀取文件前5個(gè)字節(jié)
JNIEXPORT void
JNICALLJava_demo_MainClass_read_1file(JNIEnv *env, jobject obj)
{
    //定義變量
    jclass clazz;
    jfieldID fid;
    jstring j_str;
    jstring j_newStr;
    const char *c_str = NULL;
    
    //獲取MainClass類(lèi)的Class引用
    clazz = (*env)->GetObjectClass(env, obj);
    if(NULL == clazz)
    {
        return;
    }
    
    //獲取MainClass類(lèi)實(shí)例變量message的屬性ID
    fid = (*env)->GetFieldID(env, clazz,"message", "Ljava/lang/String;");
    if(fid < 0)
    {
        return;
    }

    //獲取實(shí)例message的值
    j_str =(jstring)(*env)->GetObjectField(env, obj, fid);
    if(NULL == j_str)
    {
        return;
    }

    //將Unicode編碼的java字符串轉(zhuǎn)換為c風(fēng)格的字符串
    c_str = (*env)->GetStringUTFChars(env,j_str, NULL);
    if(NULL == c_str)
    {
        return;
    }

    int i = 0;
    //調(diào)用讀取文件函數(shù)
    i = dir_file_num((char *)c_str);
    if(i < 0)
    {
        printf("dir_file_num err!\n");
        return;
    }
}

6、代碼寫(xiě)完之后開(kāi)始制作動(dòng)態(tài)庫(kù),首先執(zhí)行
gcc -fPIC -D_REENTRANT-I/home/jdk1.8.0_77/include -I/home/jdk1.8.0_77/include/linux -cdemo_MainClass.c
生成一個(gè).o文件,這里的/home/jdk1.8.0_77/include是我主機(jī)中jni.h所在路徑,/home/jdk1.8.0_77/include/linux是jni.h所在路徑,然后執(zhí)行
gcc -shareddemo_MainClass.o -o libTestReadFile.so
生成一個(gè)libTestReadFile.so文件,這里的demo_MainClass.o就是上一步生成的.o文件。

7、這里就已經(jīng)完成了在Ubuntu下中的eclipse調(diào)用.so文件了,這時(shí)候就可以在eclipse中執(zhí)行了,然后輸入一個(gè)目錄路徑就可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 系統(tǒng)環(huán)境:64位Ubuntu14.04、eclipse 5.3版本,jdk1.8版本,vim編譯器 1、本實(shí)例是j...
    溫暖春陽(yáng)閱讀 728評(píng)論 0 0
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,271評(píng)論 25 708
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,678評(píng)論 19 139
  • 原創(chuàng) 2017-06-12 魏梅霞 老魏的新視界 被雨水洗過(guò)的蘭州,就如剛剛沐浴之后的仙女,從云端款款走來(lái),端莊嫵...
    枚紅閱讀 482評(píng)論 2 9
  • 一年到頭,大家都開(kāi)始習(xí)慣寫(xiě)年終總結(jié),每個(gè)人的故事都滾動(dòng)在我的timeline,苛責(zé)反省感謝命運(yùn)捶胸頓足咿呀撒嬌,我...
    什么名字都被注冊(cè)了閱讀 483評(píng)論 0 0

友情鏈接更多精彩內(nèi)容