动态库导出

在 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;
}
posted @ 2020-09-08 23:46  花园小花匠  阅读(452)  评论(0编辑  收藏  举报