一文兢、宏定義
宏定義可以理解為就是定義一個(gè)常量或一個(gè)函數(shù)晤斩,實(shí)現(xiàn)復(fù)用,易于統(tǒng)一維護(hù)和修改姆坚。
// 不帶參數(shù)的宏定義
#define MAX 10
// 帶參宏定義
#define M(y) y * y + 3 * y
// 宏調(diào)用
k = M(5);
二澳泵、JNIEXPORT
和 JNICALL
JNIEXPORT
與 JNICALL
實(shí)際上是 JNI
中定義的兩個(gè)宏,它們?cè)?Windows
與 Linux
分別有不同的定義兼呵。
// Windows 系統(tǒng)
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
#endif /* !_JAVASOFT_JNI_MD_H_ */
// Linux 系統(tǒng)
#define JNIIMPORT
#define JNIEXPORT __attribute__ ((visibility ("default")))
#define JNICALL
三兔辅、JNIEXPORT
和 JNICALL
宏定義作用
-
JNIEXPORT
宏定義作用
如果我們的程序需要生成動(dòng)態(tài)鏈接庫(kù) , 并且要把該動(dòng)態(tài)鏈接庫(kù)交給其它程序使用, 那么就需要在函數(shù)前加入特殊標(biāo)識(shí) , 才能在其它程序代碼中調(diào)用該動(dòng)態(tài)鏈接庫(kù)中定義的函數(shù) 。動(dòng)態(tài)鏈接庫(kù)在Windows
系統(tǒng)和Linux
系統(tǒng)中通常分別是.dll
文件 和.so
文件击喂。
那么根據(jù)不同系統(tǒng)中JNIEXPORT
宏定義的不同维苔,在預(yù)編譯時(shí)就會(huì)進(jìn)行對(duì)應(yīng)的宏替換。 -
JNICALL
宏定義作用Windows
系統(tǒng)中JNICALL
宏定義為__stdcall
,__stdcall
是一種函數(shù)調(diào)用約定 , 因?yàn)楫?dāng)程序編譯為本地機(jī)器碼由CPU
執(zhí)行時(shí)懂昂,CPU
無(wú)法明確知道每個(gè)函數(shù)應(yīng)該怎么傳參介时,于是提供了棧結(jié)構(gòu)來(lái)支持參數(shù)傳遞,但當(dāng)調(diào)用函數(shù)有多個(gè)參數(shù)時(shí)凌彬,參數(shù)應(yīng)該按照怎樣的順序入棧沸柔,然后函數(shù)調(diào)用完棧又應(yīng)該由誰(shuí)來(lái)清理,針對(duì)這兩個(gè)問(wèn)題铲敛,出現(xiàn)了一些函數(shù)調(diào)用約定褐澎,__stdcall
就是其中的一種,__stdcall
修飾的函數(shù)在調(diào)用時(shí)參數(shù)都是從右向左依次被壓入到棧中伐蒋,函數(shù)調(diào)用完在返回前由被調(diào)用函數(shù)自己負(fù)責(zé)清理堆棧工三。Linux
系統(tǒng)中JNICALL
沒(méi)有進(jìn)行定義 , 直接置空, 因此在Linux
中是可以不用寫JNICALL
宏的 迁酸。
四、JNIEXPORT
與 JNICALL
宏替換
-
Windows
系統(tǒng) :
// 使用 JNIEXPORT 和 JNICALL 的原始方法
extern "C"
JNIEXPORT void JNICALL Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
// 函數(shù)體
}
// 預(yù)編譯過(guò)程中宏替換后的方法
extern "C"
__declspec(dllexport) void __stdcall Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
// 函數(shù)體
}
-
Linux
系統(tǒng)
// 使用 JNIEXPORT 和 JNICALL 的原始方法
extern "C"
JNIEXPORT void JNICALL Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
// 函數(shù)體
}
// 預(yù)編譯過(guò)程中宏替換后的方法
extern "C"
__attribute__ ((visibility ("default"))) void Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
// 函數(shù)體
}