【问题标题】:Do I really need __declspec(dllexport) when cross-compiling a DLL with MinGW and wclang?使用 MinGW 和 wclang 交叉编译 DLL 时,我真的需要 __declspec(dllexport) 吗?
【发布时间】:2015-05-08 02:07:42
【问题描述】:

这里有类似的问题,但他们并没有完全回答我的问题:

当我使用 MinGW 和 wclang 从 Mac OS X 交叉编译 DLL 时,为什么不使用 __declspec 我的 DLL 可以正常工作?

MinGW DLL sample docs,以及我看到的每一个这样做的参考,都说在函数声明之前使用__declspec(dllexport)。然而,在我的 9,000 行库中没有代码使用它,而且 DLL 运行良好!

例如,这是一个以相同方式构建的人为示例库:

#include <stdio.h>

extern "C" {

int hello(const char* name) {
  printf("Hello, %s!\n", name);
  return 0;
}

}

在 Mac OS X 10.10.3 上编译:

w32-clang++ test.cpp -shared -o test.dll

生成美观的 DLL:

还有我的 Windows 应用程序:

#include "stdafx.h"
#include <Windows.h>
#include <iostream>

typedef int(*hellofn)(const char*);

int _tmain(int argc, _TCHAR* argv[])
{
  DWORD err;

  HINSTANCE dll = LoadLibrary(L"E:\\test.dll");
  if (!dll) {
    err = GetLastError();
    std::cout << "Can't load library: " << err << std::endl;
    return 1;
  }

  hellofn hello = (hellofn)GetProcAddress(dll, "hello");
  if (!hello) {
    err = GetLastError();
    std::cout << "Could not load the function: " << err << std::endl;
    return 2;
  }

  int ret = hello("nerd");
  std::cout << "hello() returned " << ret << std::endl;

  return 0;
}

效果很好:

我是在以某种方式向自己的脚开枪,还是有一些我没有看到的魔法?我在想 wclang (MinGW+clang) 知道以某种方式自动使用 __stdcall 并且不会破坏函数名称?

【问题讨论】:

    标签: c++ dll mingw


    【解决方案1】:

    不,在使用 MinGW 构建 DLL 时,您不需要 __declspec(dllexport); (事实上​​,我自己也经常省略)。需要注意的是,如果只有一个要包含在 DLL 中的符号被如此修饰,那么您希望导出的所有其他符号必须同样被修饰,(除非您将 --export-all-symbols 选项传递给构建 DLL 时的链接器)。

    如果您只包含未修饰的符号,则将导出所有全局符号,就像默认指定了--export-all-symbols一样。

    但是,这与 __stdcall 与 __cdecl 调用约定或名称修改无关;它仅是 DLL 导出表中符号可见性的决定因素。如果您没有将您的函数声明为__stdcall 或__cdecl,那么它们将默认为__cdecl;没问题,只要提供 DLL 和调用者都同意该约定。同样,如果两者都同意任何名称修改约定(这通常意味着,特别是在 C++ 的情况下,它们在构建时都使用相同的编译器),那么就不会有链接问题。

    【讨论】:

    • 精彩的解释。谢谢!
    猜你喜欢
    • 2017-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多