linux環境下java調用C/C++動態庫(JNI技術:參數為指針與結構體)


一、JNI技術
  JNI是Java Native Interface的縮寫,通過使用 Java本地接口書寫程序,可以確保代碼在不同的平台上方便移植.
  SUN公司發布的Java 本地接口(JNI)提供了將Java與C/C++、匯編等本地代碼集成的方案,該規范使得在 Java 虛擬機內運行的 Java 代碼能夠與其它編程語言互相操作,包括創建本地方法、更新Java對象、調用Java方法,引用 Java類,捕捉和拋出異常等,也允許Java代碼調用 C/C++或匯編語言編寫的程序和庫。作為一個標准程序接口,它沒有對底層 Java虛擬機的實現施加任何限制(特點:二進制兼容、效率高、功能強)

java與JNI數據類型對照表

1、基本數據類型

 2、引用數據類型對照表

二、Linux環境的准備(centos7)

 1、安裝JDK(注意:不能安裝openjdk,因為openjdk沒有include目錄,編譯時需要用到include目錄的頭文件

 2、安裝gcc和g++  ( yum install gcc-c++)

  3、新建Java工程,在包名為com.ywb.Native下新建"NativeCpp.java"類,方法必須使用native修飾(native即 JNI java native interface)

package com.ywb.Native; public class NativeCpp { public native void sayHello(); public native int calculate(int num1, int num2); public native void output(String url, String newUrl); }

 4、編譯生成class文件,進入工程下的target\classes目錄下,執行"javah -jni com.ywb.Native.NativeCpp",生成"com_ywb_Native_NativeCpp.h"頭文件


  4.1:com_ywb_Native_NativeCpp.h文件內容

#include <jni.h>
/* Header for class com_ywb_Native_NativeCpp */ #ifndef _Included_com_ywb_Native_NativeCpp #define _Included_com_ywb_Native_NativeCpp #ifdef __cplusplus extern "C" { #endif
/* * Class: com_ywb_Native_NativeCpp * Method: sayHello * Signature: ()V */ JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_sayHello (JNIEnv *, jobject); /* * Class: com_ywb_Native_NativeCpp * Method: calculate * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_ywb_Native_NativeCpp_calculate (JNIEnv *, jobject, jint, jint); /* * Class: com_ywb_Native_NativeCpp * Method: output * Signature: (Ljava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_output (JNIEnv *, jobject, jstring, jstring); #ifdef __cplusplus } #endif
#endif

 5、創建c++源碼文件( vim jni.cpp),將生成的頭文件"com_ywb_Native_NativeCpp.h"拷貝過來,#include "jni.h"改為#include <jni.h>,再加上自己需要實現的c++代碼邏輯
  

#include <jni.h>
/* Header for class com_ywb_Native_NativeCpp */ #ifndef _Included_com_ywb_Native_NativeCpp #define _Included_com_ywb_Native_NativeCpp #ifdef __cplusplus #include "stdio.h" #include "stdlib.h" #include "string.h"
extern "C" { #endif
/* * * Class: com_ywb_Native_NativeCpp * * Method: sayHello * * Signature: ()V * */ JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_sayHello (JNIEnv *, jobject){ printf("hello world\n"); } /* * * Class: com_ywb_Native_NativeCpp * * Method: calculate * * Signature: (II)I * */ JNIEXPORT jint JNICALL Java_com_ywb_Native_NativeCpp_calculate (JNIEnv *, jobject, jint num, jint newNum){ return num + newNum; } char* jstringToChar(JNIEnv* env, jstring jstr) { char* rtn = NULL; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("GB2312"); jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0) { rtn = (char*) malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; } env->ReleaseByteArrayElements(barr, ba, 0); return rtn; } /* * * Class: com_ywb_Native_NativeCpp * * Method: output * * Signature: (Ljava/lang/String;Ljava/lang/String;)V * */ JNIEXPORT void JNICALL Java_com_ywb_Native_NativeCpp_output (JNIEnv *env, jobject, jstring url, jstring newUrl){ char* pUrl1 = jstringToChar(env, url); char* pUrl2 = jstringToChar(env, newUrl); printf("url1 = %s\n", pUrl1); printf("url2 = %s\n", pUrl2); } #ifdef __cplusplus } #endif
#endif

6、編譯生成動態庫
 6.1:g++ -fPIC -c jni.cpp -I /home/admin/software/jdk1.8.0_202/include/ -I /home/admin/software/jdk1.8.0_202/include/linux/ 

 6.2:g++ -shared jni.o -o jni.so

  7、java調用c++動態庫

package com.ywb.Native; public class App { public static void main( String[] args ) { //windows環境下加載庫 //System.load("D:\\\JniDll.dll"); //linux下加載庫
        System.load("/root/IdeaProjects/demo/target/classes/jni.so"); NativeCpp nativeCpp = new NativeCpp(); nativeCpp.sayHello(); System.out.println(nativeCpp.calculate(15, 15)); nativeCpp.output("www.baidu.com", "https://www.cnblogs.com/ywbmaster/www.haoservice.cn"); } }

 

 

   注:可以將代碼封裝成jar包,為以后程序方便調用

 8、jni方法簽名規則
  

 可以進入Java編譯后的class文件所在的目錄,執行 javap -s  對應Java類的class文件,可以查看當前類下所有方法所對應的簽名信息

1、方法例子:

public void example1(int string, float index)

對應簽名:

(IF)V

2、方法例子:

public string example2(String string, int index,double d)

對應簽名:

(Ljava/util/String;I;D)Ljava/util/String;

3、方法例子:

public int example3(int index, String value,int[] arr)

對應簽名:

(ILjava/util/String;[I)I


 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM