这里有类似的问题,但他们并没有完全回答我的问题:
- When to use __declspec(dllexport) in C++
- Why do I need __declspec(dllexport) to make some functions accessible from ctypes?
当我使用 MinGW 和 wclang 从 Mac OS X 交叉编译 DLL 时,为什么我的 DLL 在不使用 __declspec
的情况下也能正常工作?
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
并且不会破坏函数名称?
最佳答案
不,在使用 MinGW 构建 DLL 时,您不需要 __declspec(dllexport)
; (事实上 ,我自己经常省略它)。需要注意的是,如果只有一个要包含在 DLL 中的符号被如此修饰,那么您希望导出的所有其他符号必须同样被修饰,(除非您通过 --export -all-symbols
构建 DLL 时链接器的选项)。
如果您包含仅未修饰的 符号,那么将导出所有全局符号,就像默认指定了--export-all-symbols
一样。
但是,这与 __stdcall
vs. __cdecl
调用约定或名称修改没有任何关系;它只是 DLL 导出表中符号可见性的决定因素。如果您没有将函数声明为 __stdcall
或 __cdecl
,那么它们将默认为 __cdecl
;这没问题,前提是提供 DLL 和调用者都同意该约定。同样,如果两者都同意任何名称修改约定(这通常意味着,特别是在 C++ 的情况下,它们在构建时都使用相同的编译器),那么就不会有链接问题。
关于c++ - 使用 MinGW 和 wclang 交叉编译 DLL 时,我真的需要 __declspec(dllexport) 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30114671/