dll导出命名空间下的c风格函数陷阱

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dll导出命名空间下的c风格函数陷阱相关的知识,希望对你有一定的参考价值。

1、编译阶段,如果不是重载,那么C风格的同名函数与C++风格的同名函数,就会报编译错误。
error C2084: function ‘int Test(void)‘ already has a body。

2、编译期间,编译器会检查命名空间里的函数。如SG::Test();
编译器会检测是否有函数Test()在SG命名空间里。如果没有就会报错。
error C2039: ‘Test‘ : is not a member of ‘SG‘ 

3、链接阶段,当命名空间与extern “C”组合在一起时,生成的函数代码其实是C风格的,没有命名空间修饰。
这是因为C风格里函数里没有命名空间这一概念,所以命名空间自动会被链接器忽略。

基于以上的原则,编译器链接器能够识别出基本所有的错误用法。
但是有一种情况,编译器链接器都无法识别。
那就是
DLLA中有命名空间

 namespace SG1
 {
	extern "C" __declspec(dllexport) int Test();
 }

DLLB中有命名空间SG2::Test()导出函数。

  namespace SG2
 {
	extern "C" __declspec(dllexport) void Test();
 }

在EXE中调用SG2::Test()。 这个时候,编译链接都是正确的。 但是实际运行的时候,却隐藏着一个隐患。 因为实际生成的汇编代码直接是

004EF8FF FF 15 18 1A 78 00 call  dword ptr [__imp__Test (781A18h)] 

和命名空间无关。 那么汇编代码会调用SG1下的还是SG2下的Test呢? 这两个DLL谁先引用进到EXE,先调用谁。

以上是关于dll导出命名空间下的c风格函数陷阱的主要内容,如果未能解决你的问题,请参考以下文章

google风格C/C++编程规范 --- 命名约定

C++学习(四六一)dll导出函数命名规则

MFC编写DLL怎么用C风格

如何在 dll 项目中的 C++ 中创建命名空间和构造函数?

命名空间和模块

在动态加载的 dll 中查找名称损坏的函数