美文网首页
JNI 中的宏定义

JNI 中的宏定义

作者: asdf____ | 来源:发表于2020-04-14 10:58 被阅读0次

    一、宏定义

    宏定义可以理解为就是定义一个常量或一个函数,实现复用,易于统一维护和修改。

    // 不带参数的宏定义
    #define MAX 10
    
    // 带参宏定义
    #define M(y) y * y + 3 * y
    
    // 宏调用
    k = M(5);
    

    二、JNIEXPORTJNICALL

    JNIEXPORTJNICALL 实际上是 JNI 中定义的两个宏,它们在 WindowsLinux 分别有不同的定义。

    // Windows 系统
    #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 系统
    #define JNIIMPORT
    #define JNIEXPORT  __attribute__ ((visibility ("default")))
    #define JNICALL
    
    三、JNIEXPORTJNICALL 宏定义作用
    • JNIEXPORT 宏定义作用
      如果我们的程序需要生成动态链接库 , 并且要把该动态链接库交给其它程序使用, 那么就需要在函数前加入特殊标识 , 才能在其它程序代码中调用该动态链接库中定义的函数 。动态链接库在 Windows 系统和 Linux 系统中通常分别是 .dll文件 和 .so文件。
      那么根据不同系统中 JNIEXPORT 宏定义的不同,在预编译时就会进行对应的宏替换。
    • JNICALL 宏定义作用
      • Windows 系统中 JNICALL 宏定义为 __stdcall , __stdcall 是一种函数调用约定 , 因为当程序编译为本地机器码由 CPU 执行时,CPU无法明确知道每个函数应该怎么传参,于是提供了栈结构来支持参数传递,但当调用函数有多个参数时,参数应该按照怎样的顺序入栈,然后函数调用完栈又应该由谁来清理,针对这两个问题,出现了一些函数调用约定,__stdcall 就是其中的一种,__stdcall 修饰的函数在调用时参数都是从右向左依次被压入到栈中,函数调用完在返回前由被调用函数自己负责清理堆栈。

      • Linux 系统中 JNICALL 没有进行定义 , 直接置空, 因此在 Linux 中是可以不用写 JNICALL 宏的 。

    四、JNIEXPORTJNICALL 宏替换

    • Windows 系统 :
    // 使用 JNIEXPORT 和 JNICALL 的原始方法
    extern "C"
    JNIEXPORT void JNICALL Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
        // 函数体
    }
    
    // 预编译过程中宏替换后的方法
    extern "C"
    __declspec(dllexport) void __stdcall Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
        // 函数体
    }
    
    • Linux 系统
    // 使用 JNIEXPORT 和 JNICALL 的原始方法
    extern "C"
    JNIEXPORT void JNICALL Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
        // 函数体
    }
    
    // 预编译过程中宏替换后的方法
    extern "C"
    __attribute__ ((visibility ("default"))) void Java_bytecode_NativeTest_sayWithMsgAndNum(JNIEnv *jniEnv, jobject obj, jstring msg, jint num) {
        // 函数体
    }
    

    相关文章

      网友评论

          本文标题:JNI 中的宏定义

          本文链接:https://www.haomeiwen.com/subject/xqlzmhtx.html