zoukankan      html  css  js  c++  java
  • 动态库导出

    在 Windows 平台下,导出dll/lib 一般会指定/DEF, 即导出函数的名称。下面的代码简化了导出函数的形式:

    #ifdef MM_EXPORTS
    #define MMAPI __declspec(dllexport)
    #else
    #define MMAPI __declspec(dllimport)
    #endif
    

    如果使用了上边的代码,就可以省略定义 DEF 文件。更多细节参见: https://docs.microsoft.com/en-us/cpp/build/exporting-from-a-dll-using-declspec-dllexport?view=vs-2019
    与其正交的一个概念是函数调用约定形式。即 __cdecl__stdcall。 这和 __declspec(dllexport) 是不想关的。一般C/C++ 的导出函数调用约定为__cdecl。 关于 调用约定参见 __cdecl VS __stdcall
    简而言之:

    1. __cdecl 是C/C++ 默认调用形式。 VS 编译器选项:/Gd
    int __cdecl sumExample(int a, int b);
    

    调用约定__cdecl特征是:
    参数从右开始传递,并放置在堆栈上。
    堆栈清理由调用方执行。
    函数名称通过用下划线字符"_"进行前缀来修饰。
    2. __stdcall 标准调用通常见于WIN32函数,其实就是 WINAPI__stdcall. VS编译器选项: /Gz

    #define WINAPI __stdcall
    

    声明一个 标准调用的函数:

    int __stdcall sumExample(int a, int b);
    

    __stdcall调用约定的主要特征是:
    参数传递顺序从右至左,并放置在堆栈上。
    堆栈清理由被调用方执行。
    函数名称通过前缀下划线字符并追加"@"字符和所需的堆栈空间字节数来修饰。
    3. __fastcall 略
    4. thiscall C++ 类内调用

    总结下:
    __cdecl是 C/C++的默认调用约定。此调用的优点是,它允许使用具有可变参数数的函数。缺点是它创建更大的可执行文件。
    __stdcall用于调用 Win32 API 函数。它不允许函数具有可变数量的参数。

    一个示例:

    #ifndef DPS_H
    #define DPS_H
    
    
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    
    #if (defined _WIN32) || (defined _WINDOWS) || (defined WIN32)
    #ifdef MM_EXPORTS
    #define MMAPIEXP __declspec(dllexport)
    #else
    #define MMAPIEXP __declspec(dllimport)
    #endif
    #define MMAPI __cdecl
    #else
    #define MMAPIEXP
    #define MMAPI
    #endif
          // 一个简单的回调
        typedef int(MMAPI *MMCallBack)(int handle, char* UserData);
    
        typedef struct
        {
            int a;
            int b;
            char c;
            char* d;
        }DataInfo;
    
        typedef struct
        {
            int (MMAPI* func01)(int a, int b);
            void (MMAPI* func02)(int c, DataInfo* d, MMCallBack cb);
        }MMAPIINFO;
    
          // 要导出的函数
         MMAPIEXP void MMAPI GetAPI(MMAPIINFO* api);
    #ifdef __cplusplus
    }
    #endif
    
    #endif
    

    CPP 文件

    #include "dps.h"
    
    int func01(int a, int b){
        return a + b;
    }
    
    void func02(int c, DataInfo* d, MMCallBack cb){
        cb(c,d->d);
    }
    
    
    void GetAPI(MMAPIINFO* api){
        MMAPIINFO* ret = new MMAPIINFO();
        ret->func01 = func01;
        ret->func02 = func02;
    }
    
  • 相关阅读:
    样式表中!important的用法
    ORA27101: shared memory realm does not exist问题的解决
    重置标识列的当前值
    ASP.NET Oracle数据库使用事务时注意事项
    Oracle中约束的添加方法总结
    HTML段落自动换行的样式设置
    ASP.NET应用程序中的服务器错误
    oracle中的rownum、order by与分页
    position:relative与float的区别
    Moss/Sharepoint 备份或还原时出错的处理(持续更新)
  • 原文地址:https://www.cnblogs.com/gardenofhu/p/13636446.html
Copyright © 2011-2022 走看看