对于这个问题,我猜猜:
1st,你是不是定义了“.def”并在文件中导出了你警告中的函数;
2st,你是不是从网上复制粘贴下了类似这么一段,
#ifdef EXPORT_DLL
#define BASICAPI _declspec(dllexport)
#else
#define BASICAPI _declspec(dllimport)
#endif
如果我猜对了,那么请继续往下看;
完整的警告长这样:“warning LNK4197: export 'YourFunc' specified multiple times; using first specification”
;
字面意思,导出次数多了,一次足矣,也就是说,上面的“1”和“2”存其一,即可解决该警告;
那么问题来了,用32位编译咋没事呢,64位编译器要搞哪样?
这个,下面我们统一调用约定为stdcall(至于为什么用stdcall而不用c/c++默认的cdecl,毕竟Windows API默认的函数调用约定就是stdcall),且不添加def文件,直接上图:
我们先看下直接导出c++的接口名称什么样:
(函数声明格式:__declspec(dllexport) VOID __stdcall YourFunc(INT nValue);
)
这是32位的dll:
这是64位的dll:
你没看错,二者名称是一致的,长成这样是因为c++要支持重载,而每个重载函数的名称也是不同的,这样才能区分出来;
再看下声明成c风格后导出的函数名称:
(函数声明格式:extern "C" __declspec(dllexport) VOID __stdcall YourFunc(INT nValue);
)
这是32位的dll:
这是64位的dll:
有没有看出啥区别,对喽,32位导出函数默认加了前缀,而且后面还多了个@4,这是因为函数有个4个字节的参数;
还记得导出函数默认的调用约定吗,这种命名格式是stdcall的命名风格,如果你觉得用起来不够方便,那么可以对导出函数进行重命名;
重命名有两种方式:
1.利用def文件:
YourDll.def:
;LIBRARY “YourDll”
EXPORTS
NewFuncName=_YourFunc@4
2.使用#pragma:
#pragma comment ( linker, "/EXPORT:NewFuncName=_YourFunc@4")
这样你想命什么名,都随便你了;
而64位编译器显然就不跟着调用约定走了,在声明c风格后,统一了命名格式;
虽然乍一看,一个警告不咋起眼,但里面涵盖的东西还是不少的:
1.调用约定;
2.函数导出方法;
3.导出重载函数;
4.不同的导出名称怎么解析、还原函数原型;
5.#pragma 的各种玩法;
…