當我們開始接觸JNI但是還不熟悉的時候,也許會這樣幾個問題:
- Java程序和native程序的數據類型通常是不一樣的,它們怎么相互映射的呢?
- 怎么在native方法中訪問java方法傳遞過來的數據呢?
- 在native方法中可以創建java對象嗎?
- 如何把結果返回給調用它的java方法?
讀完本文你將會明白如上問題的來龍去脈。首先我在重復一下如何編寫JNI相關的應用程序,我們必須在java方法中聲明一個native的方法,比如 public native String getLine(String prompt);這個方法具有的兩個特點是,引入了關鍵字native,它的意思是這個方法的實現由其他的語言實現,比如c/c++等。另外這個方法是以 分號結尾的,表明這個方法不包括實現。我們在上篇文章已經知道使用javah命令可以得到我們需要的header文件。下面給出java程序和相關的.h 文件的代碼
//Prompt.java
class Prompt {
private native String getLine(String prompt);
public static void main(String args[]) {
Prompt p = new Prompt();
String input = p.getLine("Type a line: ");
System.out.println("User typed: " + input);
}
static {
System.loadLibrary("prompt");
}
}
//Prompt.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Prompt */
#ifndef _Included_Prompt
#define _Included_Prompt
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Prompt
* Method: getLine
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Prompt_getLine
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
我們可以看到在Prompt.h文件中定義了我們要實現的函數的原型,我們主要關心兩點一個是方法名稱另一個是方法的參數,方法的名稱為Java_Prompt_getLine,它是由如下四部分組成
看看方法的參數,由三個參數組成分別是JNIEnv *, jobject, jstring。JNIEnv是一個JNI接口指針,它事實上是由函數表組成的,我們可以使用JNIEnv來訪問java對象。jobject是當前類的 的引用,想當與java中的this。最后一個參數是jstring,代表了我們java方法中的String prompt。
在編寫native方法的時候,無論是java基本類型還是對象我們都不能在c/c++中直接使用,必須要轉成相對應得類型,下面給出基本數據類型的對應關系。
?
Java Type | Native Type | Size in bits |
boolean
|
jboolean
|
8, unsigned |
byte
|
jbyte
|
8 |
char
|
jchar
|
16, unsigned |
short
|
jshort
|
16 |
int
|
jint
|
32 |
long
|
jlong
|
64 |
float
|
jfloat
|
32 |
double
|
jdouble
|
64 |
void
|
void
|
n/a |
關于java對象,JNI都是把它映射為jobject,為了減少編程的錯誤可能性,同時從jobject中實現了一些子類型,比如jstring等。
下面我們講述,如何在native方法中訪問java方法的參數,如何在native方法中創建java對象。我們必須清楚地知道,在訪問java參數的 時候,首先要把它轉換為相應的類型,比如參數String prompt在.h文件中為jstring。但是在實現這個方法的時候,我們不能直接對jstring進行操作,因為它與char *是不同的,我們要通過JNIEnv提供的方法把它轉換為char *。比如
char buf[128];
const char *str = env->GetStringUTFChars(prompt, 0);
printf("%s", str);
注 意一點,我們必須要主動釋放我們得到的char *,否則會造成內存泄漏。釋放的方法還是通過JNIenv提供的方法,(*env).ReleaseStringUTFChars(prompt, str);。JNIEnv同樣提供了構造String的方法,使得我們可以返回給調用者一個String類型的返回值
gets(buf);
return (*env).NewStringUTF(buf);
下面給出native實現的源代碼(c++代碼)
#include <stdio.h>
#include <jni.h>
#include "Prompt.h"
JNIEXPORT jstring JNICALL
Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt)
{
char buf[128];
const char *str = env->GetStringUTFChars(prompt, 0);
printf("%s", str);
(*env).ReleaseStringUTFChars(prompt, str);
gets(buf);
return (*env).NewStringUTF(buf);
}
在VC++中,你可以創建一個dll工程,最后把得到的prompt.dll方到Prompt.class的目錄,運行java Prompt,系統就會提示你輸入一行字符。輸入回車后則可以回顯到控制臺。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
