extern "C" 使用的原因

1)使用vc6 编写动态库,动态库源码 (dll_test.cpp) 如下:

#include <windows.h>

// _declspec(dllexport) means test() can be called by others
void _declspec(dllexport) test() 
{
    MessageBox(NULL, "call test() success!", "test", MB_OK);
}

BOOL APIENTRY DllMain(HANDLE a, DWORD b, LPVOID c)
{
    MessageBox(NULL, "in DllMain", "main", MB_OKCANCEL);

    return TRUE;
}

生成动态库为 dll_test.dll,把它放到添加到系统可以找到的目录

在“运行中调用”

rundll32 dll_test.dll,test

有如下错误提示

使用 depends 分析原因

发现在 导出的函数名前后都有乱码,将其复制后,再次执行

rundll32 dll_test.dll,?test@@YAXXZ

2)修改源码,如下:

#include <windows.h>

// _declspec(dllexport) means test() can be called by others
extern "C" void _declspec(dllexport) test() 
{
    MessageBox(NULL, "call test() success!", "test", MB_OK);
}

BOOL APIENTRY DllMain(HANDLE a, DWORD b, LPVOID c)
{
    MessageBox(NULL, "in DllMain", "main", MB_OKCANCEL);

    return TRUE;
}

编译生成动态库后,通过 depends 查看:

同时使用 rundll32 dll_test.dll,test 进行测试,有正确结果如下:

3)原因分析

extern "C" 是告诉编译器用C语言的方式给函数命名。在用VC制作DLL导出函数时,由于C++存在函数重载,为了

实现同样的函数名可因参数不同而存在,所以在VC处理这些函数时,会把函数名编译成不同的名字以便自己识别。

例如:

int test(int, int) -> test@@YAHHH@Z

float test(float, float) -> test@@YAMMM@Z

但当我们使用 extern "C" 时,编译器会标识为: _函数名

int test(int, int) -> _test

float test(float, float) -> _test

因此被 extern "C" 修饰过的函数不再具备重载能力。

原文地址:https://www.cnblogs.com/aqing1987/p/4596893.html