warning LNK4197 while building 64bit dll with MSVC

对于这个问题,我猜猜:
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:
32bit
这是64位的dll:
64bit
你没看错,二者名称是一致的,长成这样是因为c++要支持重载,而每个重载函数的名称也是不同的,这样才能区分出来;

再看下声明成c风格后导出的函数名称:
(函数声明格式:extern "C" __declspec(dllexport) VOID __stdcall YourFunc(INT nValue);

这是32位的dll:
32bit
这是64位的dll:
64bit
有没有看出啥区别,对喽,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 的各种玩法;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值