这里有类似的问题,但它们并没有完全回答我的问题:
当我使用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:
我的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
并且不会破坏函数名称吗?
答案 0 :(得分:3)
不,在使用MinGW构建DLL时,您不需要 __declspec(dllexport)
; (事实上,我经常自己省略它)。需要注意的是,如果DLL中只包含一个符号,那么您希望导出的所有其他符号必须同样装饰,(除非您通过--export-all-symbols
选项在构建DLL时使用链接器。)
如果您包含仅未修饰的符号,则会导出所有全局符号,就像默认情况下指定--export-all-symbols
一样。
但是,这与__stdcall
与__cdecl
调用约定或名称修改没有任何关系;它只是DLL导出表中符号可见性的决定因素。如果您未将功能声明为__stdcall
或__cdecl
,则默认情况下它们为__cdecl
;这没有问题,只要提供DLL和调用者同意该约定。类似地,如果两者都同意任何名称修改约定(通常意味着,特别是在C ++的情况下,它们都在构建时使用相同的编译器),那么就不存在链接问题。