在使用MinGW和wclang交叉编译DLL时,我真的需要__declspec(dllexport)吗?

时间:2015-05-08 02:07:42

标签: c++ dll mingw

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

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

MinGW DLL sample docs以及我看到的每个引用,都说在函数声明之前使用__declspec(dllexport)。然而,我的9,000行库中的代码 none 使用它,并且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:

enter image description here

我的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;
}

效果很好:

enter image description here

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

1 个答案:

答案 0 :(得分:3)

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

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

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