为什么我们需要使用:
extern "C" {
#include <foo.h>
}
Run Code Online (Sandbox Code Playgroud)
特别:
我们什么时候应该使用它?
在编译器/链接器级别发生了什么,需要我们使用它?
如何在编译/链接方面解决了需要我们使用它的问题?
如何删除此链接警告?您可以看到导致此警告的代码段.
static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
//bla bla
// Exported DLL initialization is run in context of running application
extern "C" void WINAPI InitGuiCtrlsDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(GuiCtrlsDLL);
// nothing more to do
}
Run Code Online (Sandbox Code Playgroud)
警告C4273:'InitGuiCtrlsDLL':不一致的dll链接
我还有导出和导入定义,例如:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
Run Code Online (Sandbox Code Playgroud) 根据(c)ANSI ISO/IEC 14882:2003,第127页:
链接规范嵌套.当链接规范嵌套时,最里面的规则确定语言.链接规范不会建立范围.链接规范只应在命名空间范围内发生(3.3).在链接规范中,指定的语言链接适用于声明引入的所有函数声明符,函数名和变量名的函数类型.
extern "C" void f1(void(*pf)(int));
// the name f1 and its function type have C language
// linkage; pf is a pointer to a C function
extern "C" typedef void FUNC();
FUNC f2;
// the name f2 has C++ language linkage and the
// function's type has C language linkage
extern "C" FUNC f3;
// the name of function f3 and the function's type
// have C language linkage
void (*pf2)(FUNC*);
// the name of the variable …Run Code Online (Sandbox Code Playgroud) 当我们编译C程序时,输出存储在a.out中.我们如何将编译后的输出重定向到另一个文件?
当我运行时,ldd program我得到表单的输出
linux-gate.so.1 => (0xb77ae000)
libstdc++.so.6 => /lib/libstdc++.so.6 (0xb76bc000)
libm.so.6 => /lib/libm.so.6 (0xb7691000)
libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb7674000)
libc.so.6 => /lib/libc.so.6 (0xb74c2000)
/lib/ld-linux.so.2 (0xb77af000)
Run Code Online (Sandbox Code Playgroud)
你能解释输出和原因,linux-gate.so.1并以ld-linux.so.2不同于其他条目的方式展示吗?他们的角色是什么?
所以,据我所知,这在C中是合法的:
foo.c的
struct foo {
int a;
};
Run Code Online (Sandbox Code Playgroud)
bar.c
struct foo {
char a;
};
Run Code Online (Sandbox Code Playgroud)
但功能相同是非法的:
foo.c的
int foo() {
return 1;
}
Run Code Online (Sandbox Code Playgroud)
bar.c
int foo() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并将导致链接错误(函数的多重定义foo).
这是为什么?结构名称和函数名称之间的区别是什么使C无法处理一个而不能处理另一个?这种行为也扩展到C++吗?
例如:
code1.c/.cpp
int a;
// ... and so on
Run Code Online (Sandbox Code Playgroud)
code2.c/.cpp
int a;
int main(void) {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
去编译:
$gcc code1.c code2.c # this is fine
$
$g++ code1.cpp code2.cpp # this is dead
/tmp/ccLY66HQ.o:(.bss+0x0): multiple definition of `a'
/tmp/ccnIOmPC.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
C&C++之间是否存在全局变量链接差异?
我知道 ODR、链接、static和如何extern "C"与函数配合使用。但我不确定类型的可见性,因为它们无法声明static,并且 C 中没有匿名名称空间。
特别是,我想知道以下代码如果编译为 C 和 C++ 的有效性
// A.{c,cpp}
typedef struct foo_t{
int x;
int y;
} Foo;
static int use_foo()
{
Foo f;
f.x=5;
return f.x;
}
Run Code Online (Sandbox Code Playgroud)
// B.{c,cpp}
typedef struct foo_t{
double x;
} Foo;
static int use_foo()
{
Foo f;
f.x=5.0;
return f.x;// Cast on purpose
}
Run Code Online (Sandbox Code Playgroud)
使用以下两个命令(我知道两个编译器都会根据扩展自动检测语言,因此名称不同)。
g++ -std=c++17 -pedantic -Wall -Wextra a.cpp b.cppgcc -std=c11 -pedantic -Wall -Wextra a.c b.c8.3 版本可以愉快地编译两者,没有任何错误。显然,如果两个结构符号都具有外部链接,则存在 ODR 违规,因为定义不相同。是的,编译器不需要报告它,因此我的问题是因为两者都没有报告。
这是一个后续问题的答案,以是否有可能的typedef指针到extern-"C" -函数模板中的类型?
此代码无法使用g++Visual C/C++和Comeau C/C++进行编译,并且具有基本相同的错误消息:
#include <cstdlib>
extern "C" {
static int do_stuff(int) {
return 3;
}
template <typename return_t_, typename arg1_t_>
struct test {
static void foo(return_t_ (*)(arg1_t_)) { }
};
}
int main()
{
test<int, int>::foo(&do_stuff);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
g ++说"错误:带C链接的模板",Visual C/C++发出编译器错误C2894,而Comeau C/C++说"错误:此声明可能没有extern"C"链接".
问题是,所有人都满意:
#include <cstdlib>
extern "C" {
static int do_stuff(int) {
return 3;
}
struct test {
static void foo(int (*)(int)) { }
};
}
int main()
{
test::foo(&do_stuff); …Run Code Online (Sandbox Code Playgroud)