将外部“C”放入C++代码中具体做什么?

例如:

extern "C" {
   void foo();
}

当前回答

最近,gcc似乎也支持名称篡改。即使在外部“c”中,如果使用类或重载,它也会自动损坏。

#include <stdio.h>
extern "C"{


struct myint{
    int i;
};

struct myint2
{
    int a;
    myint2(int a): a(a) {};
    operator myint() const {return myint{a};}
};

}

void f1(myint i){
    printf("%d", i.i);
}

int main(){
    myint2 a(1);
    f1(a);
}

我甚至使用了许多cpp功能。但代码编译和运行正常。如果你nm,你可以看到main没有损坏,但myint是损坏的。

其他回答

当混合使用C和C++时(即a.从C++调用C函数;b.从C调用C++函数),C++名称混乱会导致链接问题。从技术上讲,只有当被调用函数已经使用相应的编译器编译成二进制(很可能是*.a库文件)时,才会出现此问题。

因此,我们需要使用外部“C”来禁用C++中的名称篡改。

我之前对dll(动态链接库)文件使用了“extern”C“”,以使etc.main()函数“可导出”,以便稍后可以在dll的另一个可执行文件中使用。也许一个我过去使用它的例子会很有用。

DLL

#include <string.h>
#include <windows.h>

using namespace std;

#define DLL extern "C" __declspec(dllexport)
//I defined DLL for dllexport function
DLL main ()
{
    MessageBox(NULL,"Hi from DLL","DLL",MB_OK);
}

EXE

#include <string.h>
#include <windows.h>

using namespace std;

typedef LPVOID (WINAPI*Function)();//make a placeholder for function from dll
Function mainDLLFunc;//make a variable for function placeholder

int main()
{
    char winDir[MAX_PATH];//will hold path of above dll
    GetCurrentDirectory(sizeof(winDir),winDir);//dll is in same dir as exe
    strcat(winDir,"\\exmple.dll");//concentrate dll name with path
    HINSTANCE DLL = LoadLibrary(winDir);//load example dll
    if(DLL==NULL)
    {
        FreeLibrary((HMODULE)DLL);//if load fails exit
        return 0;
    }
    mainDLLFunc=(Function)GetProcAddress((HMODULE)DLL, "main");
    //defined variable is used to assign a function from dll
    //GetProcAddress is used to locate function with pre defined extern name "DLL"
    //and matcing function name
    if(mainDLLFunc==NULL)
    {
        FreeLibrary((HMODULE)DLL);//if it fails exit
        return 0;
    }
    mainDLLFunc();//run exported function 
    FreeLibrary((HMODULE)DLL);
}

仅仅通过在外部“C”中包装,并不能使任何C标头与C++兼容。当C标头中的标识符与C++关键字冲突时,C++编译器会对此进行投诉。

例如,我看到以下代码在g++中失败:

extern "C" {
struct method {
    int virtual;
};
}

Kinda是有道理的,但在将C代码移植到C++时需要记住。

由C编译器编译的函数void f()和由C++编译器编译的同名函数void f()不是同一个函数。如果您用C编写了该函数,然后尝试从C++调用它,那么链接器将查找C++函数,而找不到C函数。

extern“C”告诉C++编译器您有一个由C编译器编译的函数。一旦你告诉它它是由C编译器编译的,C++编译器就会知道如何正确调用它。

它还允许C++编译器以C编译器可以调用的方式编译C++函数。该函数将正式成为一个C函数,但由于它是由C++编译器编译的,因此它可以使用所有C++特性,并具有所有C++关键字。

它通知C++编译器在链接时以C样式查找这些函数的名称,因为在链接阶段,用C和C++编译的函数的名称不同。