我写了一个C ++函数,我需要从C程序调用。 为了使由C来调用,我指定extern "C"
的函数声明 。 然后我编译的C ++代码,但是编译器(Dignus系统/ C ++)中产生的重整名称为函数。 因此,它显然没有兑现extern "C"
。
要解决这个问题,我加extern "C"
函数定义 。 在此之后,编译器生成的函数名是从C调用
技术上, extern "C"
只需要在函数声明中指定。 这是正确的吗? (在C ++ FAQ精简版有一个很好的例子。)如果你还可以指定它的函数定义?
下面就来演示这样的例子:
/* ---------- */
/* "foo.h" */
/* ---------- */
#ifdef __cplusplus
extern "C" {
#endif
/* Function declaration */
void foo(int);
#ifdef __cplusplus
}
#endif
/* ---------- */
/* "foo.cpp" */
/* ---------- */
#include "foo.h"
/* Function definition */
extern "C" // <---- Is this needed?
void foo(int i) {
// do something...
}
我的问题可能是不正确编码的东西的结果,或者我可能已经找到了编译器错误。 在任何情况下,我想请教计算器,以确保我知道这在技术上是“正确”的方式。
在“ extern "C"
”不应该在功能上确定指标,只要声明拥有它,而且已经出现在确定指标的编制需要。 标准明确规定(7.5 / 5联动规格):
函数可以在没有链接说明被声明明确链接说明已经看到后; 在原先的声明中明确指定的链接不会受这样的函数声明。
不过,我一般不把“ extern "C"
”上把定义为好,因为它实际上是在与外部的“C”键的功能。 很多人讨厌不必要的,多余的东西是声明(就像把virtual
的方法覆盖),但我不是其中之一。
编辑:
好像我误解了问题。 不管怎么说,我想:
// foo.cpp
/* Function definition */
#include "foo.h"
void foo(int i) {
//do stuff
}
void test(int i)
{
// do stuff
}
// foo.h
#ifdef __cplusplus
extern "C" {
#endif
/* Function declaration */
void foo(int);
#ifdef __cplusplus
}
#endif
void test(int);
使用命令nm
,以查看从编译的文件中的符号:
linuxuser$ nm foo.o
00000006 T _Z4testi
U __gxx_personality_v0
00000000 T foo
这清楚地表明,函数的名称声明为extern“C”未进行重整,并在定义不需要外部的“C”关键字。
有了它,而不需要外部的“C”编写的所有C库代码会一直在C ++程序无法使用。
正好遇到这种情况......不愉快的经历。
以下是声明在我一个c
文件:
void unused_isr(void) {}
void ADC_IRQHandler(void) __attribute__ ((weak, alias("unused_isr")));
接下来某处在cpp
我定义的文件:
void ADC_IRQHandler(void) {
...
}
我忘了改向前声明:
void ADC_IRQHandler(void);
我花了一段时间之前,我想通了,我做的一切权利相对于AD转换,但我没有“外部C”添加至定义!
extern "C" void ADC_IRQHandler(void) {
...
}
只是我的两分钱为什么它可能在某些情况下是有益的习惯将它添加到定义为好。
我认为,这需要澄清这里,我刚才也有类似的问题,我花了一段时间才能得到这个明确的在我的脑海中,只有布鲁克斯摩西谈到了这个正确的,而且我认为它需要更清楚地说明.. 。
总之,头可以把你扔出,所有的编译器看到的cpp文件,如果头没有被包含在外部的“C”回你的CPP(我通常看到的),那么为extern“C”需要在cpp文件的地方(无论是在清晰度,或另一份声明),使CXX编译器能够知道C链接,使之,编译器不关心的报头,只有连接。
在extern "C"
不需要周围的定义。 你可以逃脱只是把它周围的声明。 在你的例子一注...
#ifdef __cplusplus
extern "C" {
#endif
/* Function declaration */
void foo(int);
#ifdef __cplusplus
}
#endif
您的代码正在寻找预处理器宏“ __cplusplus
”。
虽然它的普遍实现,这取决于你的编译器,这可能会或可能不会进行定义。 在你的榜样,您还可以使用extern "C"
周围的声明,但你不检查了“ __cplusplus
”宏观调控这就是为什么我怀疑它的工作,一旦你这样做。
见下面的评论-标准C ++要求__cplusplus
到由预处理器来定义宏。
它应该是既左右。 编译器需要知道使用C符号名和调用约定编译调用点(可能只看到一个声明)时,编译器也需要知道生成C符号名和编译时使用C调用约定函数定义本身(这可能看不到任何其他声明)。
现在,如果你有一个extern-C声明是在其中定义存在翻译单元可见,你可以逃脱自定义离开关的extern-C,但我不知道这是肯定。