国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C++ > 正文

通過JNI混合使用Java和C++

2019-11-11 02:24:46
字體:
來源:轉載
供稿:網友

    這文章寫的不錯,

JNI(java Native Interface)是Java語言的一部分,可以訪問非Java語言編寫的程序,也可以用于在C++程序中執行Java代碼。

步驟:

1>  編寫帶有native聲明方法的Java類,并且該方法只定義不實現,后期由c++負責實現:

// HelloCpp.java

public class HelloCpp

{

    // ...

   public native void callCpp();

    // ...

}

 

2>  由于后期的C++實現代碼最終會被編譯為一個動態庫.dll,因此需要在Java類中定義一個靜態代碼塊,提前加載該動態庫,假設動態的名字為hellocpp.dll:

// HelloCpp.java

public class HelloCpp

{

    static

    {

       System.loadLibrary("hellocpp");

    }

    public native void callCpp();

    // ...

}

 

3>  在Java類中定義main方法調用該native方法:

// HelloCpp.java

public class HelloCpp

{

    static

    {

       System.loadLibrary("hellocpp");

    }

    public native void callCpp();

    public static void main(String[] args)

    {

       System.out.PRintln("***** JNI Test *****");

       HelloCpp instance = new HelloCpp();

       instance.callCpp();      // 調用native方法

    }

}

 

4>  編譯包含native方法的Java類,生成class字節碼文件:

javac HelloCpp.java        // 生成HelloCpp.class

 

5>  生成與native方法對應的.h頭文件:

javah –jni HelloCpp         // 生成HelloCpp類對于的頭文件HelloCpp.h

 

// HelloCpp.h

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class HelloCpp */

#ifndef _Included_HelloCpp

#define _Included_HelloCpp

#ifdef __cplusplus

extern "C" {

#endif

/*

 * Class:     HelloCpp

 * Method:    callCpp

 * Signature: ()V

 */

JNIEXPORT void JNICALL Java_HelloCpp_callCpp(JNIEnv* env, jobject this);

#ifdef __cplusplus

}

#endif

#endif

 

6>  使用C++實現native方法:

// HelloCpp.cpp

#include "HelloCpp.h"

#include <jni.h>

#include <iostream>

 

JNIEXPORT void JNICALL Java_HelloCpp_callCpp(JNIEnv* env, jobject this)

{

    std::cout << "C++ Implementation" << std::endl;

}

 

7>  編譯生成動態庫hellocpp.dll:

g++ -Wl,--kill-at –shared –I D:/jdk1.7.0_75/include –I D:/jdk1.7.0_75/include/win32 HelloCpp.cpp –o hellocpp.dll

 

8>  調用hellocpp.dll來運行Java程序:

Java HelloCpp

結果如下:

***** JNI Test *****

C++ Implementation

 

說明:

JNIEXPORT void JNICALL Java_HelloCpp_callCpp(JNIEnv* env, jobject this);

JNIEXPORT和JNICALL是宏。

JNIEnv*指向一個位置,該位置包含一個指向函數表的指針,表中的每一項都是一個指向JNI函數的指針,native方法通過JNI函數訪問JVM的中的數據 ,如下所示:

第二個參數對于非靜態方法為jobject,對于靜態方法為jclass。jobject表示調用native方法對象自身的引用,如同C++中的this指針;jclass表示定義native方法的類的引用。

 

如下介紹帶有參數返回值的native方法:

// Prompt.java

復制代碼
 1 class Prompt 2 { 3     static 4     { 5         System.loadLibrary("Prompt"); 6     } 7     private native String GetLine(String prompt); 8      9     public static void main(String[] args)10     {11         Prompt p = new Prompt();12         String input = p.GetLine("Enter a line:");13         System.out.println("Your Input is: " + input);14     }15 }     復制代碼

 

// Prompt.h

復制代碼
 1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class Prompt */ 4  5 #ifndef _Included_Prompt 6 #define _Included_Prompt 7 #ifdef __cplusplus 8 extern "C" { 9 #endif10 /*11  * Class:     Prompt12  * Method:    GetLine13  * Signature: (Ljava/lang/String;)Ljava/lang/String;14  */15 JNIEXPORT jstring JNICALL Java_Prompt_GetLine(JNIEnv* env, jobject _this, jstring prompt);16 17 #ifdef __cplusplus18 }19 #endif20 #endif復制代碼

 

// Prompt.cpp

復制代碼
 1 #include "Prompt.h" 2 #include <iostream> 3  4 JNIEXPORT jstring JNICALL Java_Prompt_GetLine(JNIEnv* env, jobject _this, jstring prompt) 5 { 6     char buf[1024]; 7     const char* str; 8     str = env->GetStringUTFChars(prompt, NULL);            /* 獲得傳入的字符串,將其轉換為native Strings */ 9     if(str == NULL)                                        /* str == NULL意味著JVM為native String分配內存失敗 */10     {11         return NULL;12     }13     std::cout << str;                                        /* 顯示傳入的字符串參數 prompt */ 14     env->ReleaseStringUTFChars(prompt, str);                /* 通知JVM釋放String所占的內存 */15     16     std::cin.get(buf, 1024);17     return env->NewStringUTF(buf);                        /* 構造新的Java.lang.String,如果JVM分配內存失敗,則拋出OutOfMemoryError,并且返回NULL */18 }復制代碼

 

補充信息:

:: UTF-8字符串以’/0’結尾,而Unicode字符串則不是。如果需要獲得Unicode格式的jstring的長度,可以使用GetStringLength;如果需要獲得UTF-8格式的jstring的長度,可以先使用GetStringUTFChars,在其結果上使用strlen,或者直接使用GetStringUTFLength

:: GetStringUTFChars的第二個參數為jboolean *isCopy,其指向分配的內存空間,如果isCopy被設為JNI_TRUE,那么返回的String是Java String的一個副本;如果被設為JNI_FALSE,那么返回一個指向Java String本身的指針,此時不允許修改返回的String。

:: 函數對Get/ReleaseStringCritical的作用于Get/ReleaseStringChars類似,但是對于程序員而言,該函數對之間的代碼相當于“臨界區”。在該“臨界區”內,native代碼不能調用任何的JNI函數,否則將引起當前線程阻塞。

:: GetStringRegion/GetStringUTFRegion將Unicode格式的String復制到預分配的緩沖區中,由于不需要JVM分配內存,因此也就不需要釋放操作:

按 Ctrl+C 復制代碼JNIEXPORT jstring JNICALL Java_Prompt_GetLine(JNIEnv* env, jobject _this, jstring prompt){    char inbuf[1024], outbuf[1024];    int len = env->GetStringUTFLength(prompt);    env->GetStringUTFRegion(prompt, 0, len, outbuf);    std::cout << outbuf;        std::cin.get(inbuf, 1024);    return env->NewStringUTF(inbuf);    }

 

總結:

1>  數據類型對應關系表:

Java 類型

本地 C 類型

實際表示的 C 類型(Win32)

boolean

jboolean

unsigned char

byte

jbyte

signed char

char

jchar

unsigned short

short

jshort

short

int

jint

long

long

jlong

__int64

float

jfloat

float

double

jdouble

double

void

void

N/A

 

2>  JNI字符串函數

JNI函數

描述

版本

GetStringChars

ReleaseStringChars

獲得/釋放一個Unicode格式的字符串指針,可能返回一個字符串的副本

JDK 1.1

GetStringUTFChars

ReleaseStringUTFChars

獲得/釋放一個UTF-8格式的字符串指針,可能返回一個字符串的副本

JDK 1.1

GetStringLength

返回Unicode格式字符串的長度

JDK 1.1

GetStringUTFLength

返回UTF-8格式字符串的長度

JDK 1.1

NewString

根據Unicode格式的C字符串創建一個Java字符串

JDK 1.1

NewStringUTF

根據UTF-8格式的C字符串創建一個Java字符串

JDK 1.1

GetStringCritical

ReleaseStringCritical

獲得/釋放一個Unicode格式的字符串指針,可能返回一個字符串的副本【在該函數對區間內,不能使用任何JNI函數】

JDK 1.2

GetStringRegion

將Unicode格式的String復制到預分配的緩沖區中

JDK 1.2

GetStringUTFRegion

將UTF-8格式的String復制到預分配的緩沖區中

JDK 1.2

備注:

首先,設置項目依賴的本地庫,例如把opencv-246.jar引入到項目的lib庫中,opencv-246.jar在opencv的安裝目錄下的/build/java下。

其次,設置項目的native庫,把opencv_java246.dll文件所在的目錄加入到Native library location中,opencv_java246.dll在opencv安裝目錄下的/build/java/x86或/build/java/x64中,前者是32位系統用的,后者64位。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 沂南县| 孟津县| 铜陵市| 辉县市| 宣武区| 临泉县| 九龙县| 乌鲁木齐市| 于田县| 长春市| 台州市| 龙江县| 江阴市| 收藏| 印江| 邵阳县| 牙克石市| 太仓市| 赤城县| 光山县| 宽城| 长岭县| 靖江市| 江陵县| 双牌县| 上林县| 辽阳县| 瑞昌市| 三台县| 神木县| 揭东县| 龙南县| 久治县| 隆子县| 临沂市| 云安县| 资兴市| 安远县| 桦甸市| 松原市| 松桃|