我在Boost代码中找到了这样的例子。
namespace boost {
namespace {
extern "C" void *thread_proxy(void *f)
{
....
}
} // anonymous
void thread::thread_start(...)
{
...
pthread_create(something,0,&thread_proxy,something_else);
...
}
} // boost
您到底为什么需要这个extern "C"
很明显,thread_proxy
函数是私有的内部函数,我不希望它被修改为"thread_proxy“,因为我实际上根本不需要修改它。
事实上,在我写的所有运行在许多平台上的代码中,我从来没有使用过extern "C"
,这对于正常的函数来说是可以正常工作的。
为什么要添加extern "C"
?
我的问题是extern "C"
函数污染了全局名称空间,而且它们实际上并不像作者期望的那样是隐藏的。
这不是复制品!我不是在说破坏和外部链接。很明显,在这段代码中,外部链接是不需要的!
回答:C和C++函数的调用约定不一定相同,因此您需要使用C调用约定创建一个。参见C++标准的7.5 (p4)。
发布于 2010-04-08 00:37:54
很明显,
thread_proxy
函数是私有的内部函数,我不希望它被修改为"thread_proxy“,因为我实际上根本不需要修改它。
无论如何,它仍然会被损坏。(如果不是extern "C"
的话)这就是编译器的工作方式。我同意编译器可能会说“这不一定需要修改”,但标准对此只字不提。也就是说,mangling在这里不起作用,因为我们不会尝试链接到函数。
事实上,在我写的所有代码中,我从来没有使用过
extern "C"
,这些代码可以在许多平台上运行,而且它可以按原样使用普通函数。
在不同平台上编写与extern "C"
无关。我希望所有标准C++代码都能在具有标准C++兼容编译器的所有平台上工作。
extern "C"
与C的接口有关,pthread是的一个库。它不仅不会破坏名称,而且还确保它可以使用C调用约定进行调用。这是需要保证的调用约定,因为我们不能假设我们是在某个编译器、平台或体系结构上运行的,所以尝试这样做的最好方法是使用提供给我们的功能:extern "C"
。
我的问题是
extern "C"
函数污染了全局名称空间,并且它们并不像作者期望的那样实际上是隐藏的。
上面的代码没有任何污染。它在一个未命名的名称空间中,并且不能在转换单元之外访问。
发布于 2010-04-08 00:37:48
extern "C"
链接并不一定意味着只有名称损坏被抑制。事实上,可能有一种编译器将extern "C"
视为不同的调用约定。
该标准将其完全开放为实现定义的语义。
发布于 2010-04-08 00:42:56
这个问题是有效的-尽管该函数被传递到一个C库,但该C库根本没有链接到C++代码。它只给出了函数的地址,所以它对函数的名称没有任何兴趣。
关键是,extern "C"
是最接近跨平台的方式,它告诉编译器让函数在该平台上使用标准的C调用约定(即,参数和返回值应该如何在堆栈上传递)。
不幸的是,它还具有在全局级别创建外部链接器符号的副作用。但这可以通过使用像boost_detail_thread_proxy
这样的名称来缓解。
https://stackoverflow.com/questions/2594178
复制相似问题