導航:首頁 > 編程語言 > jni編程指南pdf

jni編程指南pdf

發布時間:2023-01-03 11:03:04

① JNI編程android.mk文件怎麼添加

android.mk 是Android開發中,用來編譯JNI代碼的
在開發工具中,new JNI 即可創建一個 android.mk文件
一個Android.mk文件可以編譯多個模塊,每個模塊屬下列類型之一:
APK程序 一般的Android程序,編譯打包生成apk文件
java庫 java類庫,編譯打包生成jar文件
C\C++應用程序 可執行的C\C++應用程序
C\C++靜態庫 編譯生成C\C++靜態庫,並打包成.a文件
C\C++共享庫 編譯生成共享庫(動態鏈接庫),並打包成.so文, 有且只有共享庫才能被安裝/復制到您的應用軟體(APK)包中。

② JNI編程之如何傳遞參數(二)——數組類型的傳遞

來看一個傳遞int數組的例子,Java程序就不寫了,JNIEXPORT jintJNICALL Java_IntArray_sumArray(JNIEnv *env, jobject obj, jintArray arr) { jint *carr; carr = env->GetIntArrayElements(arr, false); if(carr == NULL) { return 0; /* exception occurred */ } jint sum = 0; for(int i=0; i<10; i++) { sum += carr[i]; } env->ReleaseIntArrayElements(arr, carr, 0); return sum; }這個例子中的GetIntArrayElements和ReleaseIntArrayElements函數就是JNI提供用於處理int數組的函 數。如果試圖用arr[i]的方式去訪問jintArray類型,毫無疑問會出錯。JNI還提供了另一對函數GetIntArrayRegion和 ReleaseIntArrayRegion訪問int數組,就不介紹了,對於其他基本類型的數組,方法類似。二維數組和String數組在JNI中,二維數組和String數組都被視為object數組,因為數組和String被視為object。仍然用一個例子來說明,這次是一個二維int數組,作為返回值。JNIEXPORTjobjectArray JNICALL Java_ObjectArrayTest_initInt2DArray(JNIEnv *env, jclasscls, int size) { jobjectArray result; jclass intArrCls = env->FindClass("[I"); result = env->NewObjectArray(size, intArrCls, NULL); for (int i = 0; i < size; i++) { jint tmp[256]; /* make sure it is large enough! */ jintArray iarr = env->NewIntArray(size); for(int j = 0; j < size; j++) { tmp[j] = i + j; } env->SetIntArrayRegion(iarr, 0, size, tmp); env->SetObjectArrayElement(result, i, iarr); env->DeleteLocalRef(iarr); } return result; }上面代碼中的第三行, jobjectArray result; 因為要返回值,所以需要新建一個jobjectArray對象。jclass intArrCls = env->FindClass("[I"); 是創建一個jclass的引用,因為result的元素是一維int數組的引用,所以intArrCls必須是一維int數組的引用,這一點是如何保證的 呢?注意FindClass的參數"[I",JNI就是通過它來確定引用的類型的,I表示是int類型,[標識是數組。對於其他的類型,都有相應的表示方 法,Z booleanB byteC charS shortI intJ longF floatD doubleString是通過「Ljava/lang/String;」表示的,那相應的,String數組就應該是「[Ljava/lang/String;」。還是回到代碼, result = env->NewObjectArray(size, intArrCls, NULL); 的作用是為result分配空間。

③ JNI編程之如何傳遞參數(一)——String參數的傳遞

先看一個例子,class Prompt { // native method that prints a prompt and reads a line 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"); } }在這個例子中,我們要實現一個native方法 String getLine(String prompt); 讀入一個String參數,返回一個String值。通過執行javah -jni得到的頭文件是這樣的#include<jni.h> #ifndef_Included_Prompt #define_Included_Prompt #ifdef __cplusplus extern"C" { #endif JNIEXPORT jstringJNICALL Java_Prompt_getLine(JNIEnv *env, jobject this, jstring prompt); #ifdef __cplusplus } #endif #endifjstring是JNI中對應於String的類型,但是和基本類型不同的是,jstring不能直接當作C++的string用。如果你用 cout << prompt << endl; 編譯器肯定會扔給你一個錯誤信息的。其實要處理jstring有很多種方式,這里只講一種我認為最簡單的方式,看下面這個例子,#include"Prompt.h" #include<iostream> JNIEXPORT jstringJNICALL Java_Prompt_getLine(JNIEnv *env, jobject obj, jstring prompt) { const char* str; str = env->GetStringUTFChars(prompt, false); if(str == NULL) { return NULL; /* OutOfMemoryError already thrown */ } std::cout << str << std::endl; env->ReleaseStringUTFChars(prompt, str); char* tmpstr = "return string succeeded"; jstring rtstr = env->NewStringUTF(tmpstr); return rtstr; }在上面的例子中,作為參數的prompt不能直接被C++程序使用,先做了如下轉換 str = env->GetStringUTFChars(prompt, false); 將jstring類型變成一個char*類型。返回的時候,要生成一個jstring類型的對象,也必須通過如下命令

④ 請教JNI編程中C調用Java實現中NullPointerException問題

java 與 C++ 兩種編程語言,它們之間的相互調用:
1、java 調用C++編寫的dll,可使用JNI 或 Jawin 開源項目(推薦第二種方法)。
2、C++ 調用java 的變數、方法,通過JNI (Java Native Interface)與java類交互。

----操作步驟(只總結第二個)-----
(1) vc6.0編譯C++程序,開發環境設置:工具--》選項--》工具,工具標簽下:選擇「include files」,加入頭文件目錄:C:\Program Files\Java\jdk1.5.0\include 和 C:\Program Files\Java\jdk1.5.0\include\win32 ;選擇「Libary files"下,加入LIB目錄:C:\Program Files\Java\jdk1.5.0\lib 。會編譯成exe文件。
執行程序環境設置: Path環境變數加入:C:\Program Files\Java\jdk1.5.0\jre\bin\client (jvm.dll所在目錄),若不加入path會提示,執行時找不到jvm.dll.

(2)GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
//([Ljava/lang/String;)V 是main()簽名
在java程序目錄下執行:javap -s -p ClassDemo (注:ClassDemo.java 已經編譯)
取main 下面的語句 :: Signature: ([Ljava/lang/String;)V

(3)附代碼示例:

java程序
import java.io.*;
public class DemoMain{
public static void main(String[] args) throws java.io.IOException, java.lang.NullPointerException
{
System.out.println("This is a test.");
}
}

C++程序:
#ifndef __cplusplus
#define __cplusplus
#endif
#include "jni.h"
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma comment (lib,"C:\\Program Files\\Java\\jdk1.5.0\\lib\\jvm.lib") // 動態調用lib
#pragma warning(disable: 4129) // 關閉 warning, 4129
void main() {
LoadLibrary("C:\\Program Files\\Java\jre1.5.0\\bin\\client\\jvm.dll"); // 動態調用dll
JavaVM *jvm;
JNIEnv *env;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
options[0].optionString = "-Djava.compiler=NONE";
options[1].optionString = "-Djava.classpath=.";
options[2].optionString = "-verbose:jni";
vm_args.version = JNI_VERSION_1_4;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
jint res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); // 創建虛擬機
if (res < 0) {
fprintf(stderr, "Can't create Java VM\n");
exit(1);
};
jclass cls = env->FindClass("DemoMain");
if (cls == 0) printf("Sorry, I can't find the class");
fprintf(stdout, "This is invokeSimplified4.\n");
jmethodID get_main_id;
if(cls != NULL)
{
get_main_id =env->GetStaticMethodID(cls,"main","([Ljava/lang/String;)V");
fprintf(stdout, "This is invokeSimplified5.\n");
if(get_main_id != NULL )
{
jclass string = env->FindClass("java/lang/String");
jobjectArray args = env->NewObjectArray(0,string, NULL);
fprintf(stdout, "This is invokeSimplified6.\n");
int i = env->CallIntMethod(cls, get_main_id, args);
fprintf(stdout, i+ "This is invokeSimplified7.\n");
}
}
jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory\n");
}

⑤ 如何在JNI編程中使用logCat

在android編程java代碼中,我們知道,可以使用Log.v等一些將日誌輸出到logcat,然後我們就可以看到日誌輸出信息。當然,也可以在外殼里使用亞行 NDK是否支持了。以往,在JNI編程中,調試本地介面方法比較困難,往往都是採用打日誌的方式將日誌輸出到文件。今天,在目錄
/build/platforms/android-8/arch-arm/usr/include/android/log.h
下發現的Android NDK提供的頭文件,打開瞧瞧

[CPP]鑒於plain
/ *
*版權所有(C)2009年的Android開源項目
*
* Apache許可證下授權,版本2.0(以下簡稱「許可證」);
*您不能使用這個文件除了在遵守許可。
*您可以在獲得許可證的副本
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*除非適用法律要求或書面同意,軟體
*許可證下發布分布在一個「AS IS」的基礎上,
*無擔保或任何形式的條件,明示或暗示的保證。
*請參閱許可證特定語言的管理許可權和
*許可證下的局限性。
* /

#ifndef的_ANDROID_LOG_H
#定義_ANDROID_LOG_H

/ ******************* *****************
*
*重要提示:
*
*這個文件是Android的一套穩定的系統頭的一部分
*揭發了Android NDK(原生開發套件),因為
*平台1.5版
*
*第三方源代碼和二進制代碼依賴於定義
*這里被凍結在所有UPCOMING平台版本。
*
* - 不要修改ENUMS(除非您添加新的32位值)
* - 不要修改常數或功能宏
* - 請勿更改功能的簽名ANY WAY
* - 請勿更改結構的布局和大小
* /

/ *
*支持常式將消息發送到了Android的內核日誌緩沖區,
*可以在以後通過「logcat的」實用工具進行訪問。
*
*每個日誌消息必須有
* - 優先
* - 日誌標簽
* - 一些文本
*
*標記通常對應於發射所述日誌消息的組件,
*並應相當小。
*
*日誌消息文本可能會被截斷,以不到一個特定實現
*限制(如1023字元)。
*
*請注意,換行符(「/ N」)將被自動添加到您的
*日誌消息,如果不是已經存在。這是不可能的發送幾個消息
*,並讓它們出現在logcat中一行。
*
*請使用日誌切勿過量:
*
* - 發送日誌消息吃CPU和減慢你的應用程序和
*系統。
*
* - 圓形日誌緩沖區是非常小(<64KB),發送大量郵件
*可能會蹬從系統的其餘部分等重要日誌消息。
*
* - 在發布版本,只發送日誌消息來解釋例外
*條件。
*
*注意:這些功能必須由/system/lib/liblog.so實施
* /

的#include <STDARG.H>

的#ifdef __cplusplus
外部的「C」{
#ENDIF

/ *
* Android的日誌優先順序值,以升序的優先順序。
* /
的typedef枚舉android_LogPriority {
ANDROID_LOG_UNKNOWN = 0,
ANDROID_LOG_DEFAULT,/ *僅供SetMinPriority()* /
ANDROID_LOG_VERBOSE,
ANDROID_LOG_DEBUG,
ANDROID_LOG_INFO,
ANDROID_LOG_WARN,
ANDROID_LOG_ERROR,
ANDROID_LOG_FATAL,
ANDROID_LOG_SILENT,/ *僅供SetMinPriority();必須是最後一個* /
} android_LogPriority;

/ *
*發送一個簡單的字元串日誌。
* /
INT __android_log_write(INT PRIO,為const char *標記,為const char *文本);

/ *
*發送一個格式化字元串到日誌,使用如printf(FMT,...)
* /
INT __android_log_print(INT PRIO,為const char *標記,為const char * FMT,...)
#如果定義(__ GNUC__)
__attribute__((格式(printf的,3,4)))
#ENDIF
;

/ *
* __android_log_print(的一種變體),需要一個va_list的列表
*額外的參數。
* /
INT __android_log_vprint(INT PRIO,為const char *標記,
為const char * FMT,va_list的AP);

/ *
*登錄斷言失敗和SIGTRAP過程中有機會
*檢查它,如果一個調試器附加。它使用了致命的優先順序。
* /
無效__android_log_assert(為const char * COND,為const char *標記,
為const char * FMT,...)
#如果定義(__ GNUC__)
__attribute__((不返回的))
__attribute__((格式(printf的,3,4)))
#ENDIF
;

的#ifdef __cplusplus
}
#ENDIF

#ENDIF / * * _ANDROID_LOG_H /

請仔細閱讀這個頭文件,我們會發現,Android的NDK完全支持JNI本地方法調試。它提供4個函數供我們使用,如下

[CPP]鑒於plain
/ *
*發送一個簡單的字元串日誌。
* /
INT __android_log_write(INT PRIO,為const char *標記,為const char *文本);

/ *
*發送一個格式化字元串到日誌,使用如printf(FMT,...)
* /
INT __android_log_print(INT PRIO,為const char *標記,為const char * FMT,...)

/ *
* __android_log_print(的一種變體),需要一個va_list的列表
*額外的參數。
* /
INT __android_log_vprint(INT PRIO,為const char *標記,
為const char * FMT,va_list的AP);

/ *
*登錄斷言失敗和SIGTRAP過程中有機會
*檢查它,如果一個調試器附加。它使用了致命的優先順序。
* /
無效__android_log_assert(為const char * COND,為const char *標記,
為const char * FMT,...)

我們可以將本地方法調試信息發送到logcat里。(是不是很爽,以後調試本地方法就不用那麼糾結了^_^)
要使用這幾個函數,就必須在本地文件中加入如下包含語句
的#include <機器人/ log.h>

⑥ Android中怎麼通過JNI編程去發送adb指令控制手機

編寫一個C程序,使用system(「cmd
line") ,直接調用命令行程序即可。更復雜調用可以用execv 之類系統調用

⑦ jni編程錯誤: Exception in thread main java.lang.UnsatisfiedLinkError:Test.print(Ljava/lang/String)

java這方面沒有什麼問題,你要把你的c/c++的代碼貼出來才好分析原因
JNIEXPORT jstring JNICALL Java_com_it_Test_print (JNIEnv * env, jobject jobj, jstring string){
const char * test=env->GetStringUTFChars(string,NULL);
cout<<test<<endl;
env->ReleaseStringUTFChars(string,test);
}

⑧ 如何在Android JNI編程中實現對信號量的操作

可以。實現JNI原生函數源文件: 新建com_lucyfyr_HelloWorld.c文件: #include #define LOG_TAG "HelloWorld" #include /* Native interface, it will be call in java code */ JNIEXPORT jstring JNICALL Java_com_lucyfyr_HelloWorld_printJNI...

閱讀全文

與jni編程指南pdf相關的資料

熱點內容
dvd光碟存儲漢子演算法 瀏覽:756
蘋果郵件無法連接伺服器地址 瀏覽:962
phpffmpeg轉碼 瀏覽:671
長沙好玩的解壓項目 瀏覽:142
專屬學情分析報告是什麼app 瀏覽:564
php工程部署 瀏覽:833
android全屏透明 瀏覽:732
阿里雲伺服器已開通怎麼辦 瀏覽:803
光遇為什麼登錄時伺服器已滿 瀏覽:301
PDF分析 瀏覽:484
h3c光纖全工半全工設置命令 瀏覽:141
公司法pdf下載 瀏覽:381
linuxmarkdown 瀏覽:350
華為手機怎麼多選文件夾 瀏覽:683
如何取消命令方塊指令 瀏覽:349
風翼app為什麼進不去了 瀏覽:778
im4java壓縮圖片 瀏覽:362
數據查詢網站源碼 瀏覽:150
伊克塞爾文檔怎麼進行加密 瀏覽:890
app轉賬是什麼 瀏覽:163