extern C 不能在类级别使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1025345/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
extern C can not be used at class level?
提问by George2
Just want to confirm in Windows environment, VSTS 2008 + C++ project, we could only apply extern C to function level, not be able to apply to class level (so that all member functions from the class use C language name mangling)? I have tried several ways, but always compile error.
只是想确认在Windows环境,VSTS 2008 + C++项目中,我们只能将extern C应用于函数级别,不能应用于类级别(这样类中的所有成员函数都使用C语言名称修改)?我尝试了几种方法,但总是编译错误。
thanks in advance, George
提前致谢,乔治
回答by Pavel Minaev
You can sort of apply extern "C"
to a member function via a very convoluted (but entirely legal) hack:
您可以extern "C"
通过一个非常复杂(但完全合法)的 hack来应用到成员函数:
extern "C" typedef int bar_t(int x);
struct foo {
bar_t bar; // yes, this declares a nonstatic member function!
};
int foo::bar(int x) { return x; } // definition
This is possible according to ISO C++03 9.3[class.mfct]/9:
根据 ISO C++03 9.3[class.mfct]/9,这是可能的:
a member function can be declared (but not defined) using a typedef for a function type. The resulting member function has exactly the same type as it would have if the function declarator were provided explicitly, see 8.3.5.
可以使用函数类型的 typedef 声明(但未定义)成员函数。结果成员函数的类型与显式提供函数声明符时的类型完全相同,参见 8.3.5。
However, this doesn't really buy you anything, because of ISO C++03 7.5[dcl.link]/4:
然而,由于 ISO C++03 7.5[dcl.link]/4,这并没有真正给你买什么:
A C language linkage is ignored for the names of class members and the member function type of class member functions.
对于类成员的名称和类成员函数的成员函数类型,将忽略 AC 语言链接。
回答by Todd Gardner
extern "c" uses c-style linking; that is, the raw function name is what exposed from the library. Because it is just a raw function name, none of the C++-only features will work with it, including methods or extern data members in namespaces, classes, structs or unions.
extern "c" 使用 c 风格的链接;也就是说,原始函数名称是从库中公开的。因为它只是一个原始函数名,没有任何仅 C++ 的特性可以使用它,包括命名空间、类、结构或联合中的方法或外部数据成员。
Clarifying: Structs and unions are in C, but have no member functions, so their member functions in C++ cannot be exported in a c-style (and the struct and union definitions need not be exported, since it is already in the header)
澄清:结构和联合在 C 中,但没有成员函数,所以它们在 C++ 中的成员函数不能以 c 样式导出(结构和联合定义不需要导出,因为它已经在标题中)
回答by Max Lybbert
Looking at a comment you placed on a previous answer ("[M]y question is just whether we could apply extern C
at class level so that all functions in the class automatically has C style name mangling?", the answer is 'extern "C"
doesn't quite work that way.'
查看您对先前答案的评论(“[M]y 问题只是我们是否可以extern C
在类级别应用,以便类中的所有函数自动具有 C 样式名称修改?”,答案是 'extern "C"
不完全是那样工作。
Syntactically, extern "C"
can be applied to either a single statement of a curly-delimited block:
从语法上讲,extern "C"
可以应用于卷曲分隔块的单个语句:
extern "C" int my_foo(int i)
{
...
}
extern "C" {
int my_bar(int i)
{
...
}
int my_baz(int i)
{
...
}
}
It's common to use extern "C"
with the appropriate #ifdef __cplusplus
guards on entire C headers.
在整个 C 头文件上使用extern "C"
适当的#ifdef __cplusplus
保护是很常见的。
Semantically, the actual effect of applying extern "C"
will only apply to "normal" (i.e., non-class) functions and pointers to functions. Of course you cannot apply it to a C++ template. Nor can you apply it to class methods (because a class method needs to know which object it was called on, and C-style linkage does not have any way to pass that information in to the function).
从语义上讲,应用的实际效果extern "C"
仅适用于“普通”(即非类)函数和函数指针。当然,您不能将其应用于 C++ 模板。您也不能将它应用于类方法(因为类方法需要知道它被调用的是哪个对象,而 C 风格的链接没有任何方法将该信息传递给函数)。
It ispossible to apply extern "C"
on functions that exist in a namespace, but the namespace information will simply disappear when used via C.
它是可以应用extern "C"
上存在的命名空间中的功能,而是通过C.使用时命名空间的信息将完全消失
Update
更新
If you already have a class (we'll use a POD classfor simplicity), and you want to make it usable from C, you'll need to apply extern "C"
to a function callable in C. Unfortunately this gets ugly even in simple cases:
如果你已经有一个类(为了简单起见,我们将使用一个POD 类),并且你想让它在 C 中可用,你需要申请extern "C"
一个在 C 中可调用的函数。不幸的是,即使在简单的情况下,这也会变得丑陋:
// in the header file
#ifdef __cplusplus
namespace X {
#endif
struct A
{
int x;
#ifdef __cplusplus
A() : x(5) { }
int foo()
{
return x += 5;
}
#endif
};
#ifdef __cplusplus
extern "C" {
#endif
int A_foo(struct A a);
struct A A_create();
#ifdef __cplusplus
}
}
#endif
// in the .cc file
#include "try.h"
namespace X {
extern "C" {
int A_foo(A* a)
{
return a.foo();
}
A A_create()
{
return A();
}
}
}
// in the .c file
#include <stdio.h>
#include "try.h"
int main()
{
struct A a = A_create();
printf("%d", A_foo(a));
}
Using gcc you would compile this as follows:
使用 gcc 编译如下:
- the C++ file:
g++ try.cc -c -o try.o
- the C file :
gcc try.c try.o
- C++ 文件:
g++ try.cc -c -o try.o
- C文件:
gcc try.c try.o
There are a few important points:
有几个重要的点:
- If your C++ file calls into the STL behind the scenes, or calls
new
ordelete
(ornew[]
ordelete[]
) you will need to link the final program to the C++ runtime library (the command line switch for this in gcc is-lstdc++
. - You're probably going to want to pass identical optimization flags when compiling both the C and C++ code (optimization can affect the size of the objects, and if the size doesn't match you can get into a lot of trouble). Ditto for multithreading.
- You can use exceptions all you want in the C++ code, but once they cross C code all bets are off.
- If you want something more complex you'll probably want to look at the PIMPL pattern.
- When a struct falls out of scope in C code the C++ destructor is notcalled (some compilers may promise to do so, but it's not standard). If you need to do any clean up on these objects you'll need to call an extern "C" function that calls the destructor.
- 如果您的 C++ 文件在幕后调用 STL,或者调用
new
ordelete
(或new[]
或delete[]
),您将需要将最终程序链接到 C++ 运行时库(gcc 中的命令行开关是-lstdc++
. - 在编译 C 和 C++ 代码时,您可能想要传递相同的优化标志(优化会影响对象的大小,如果大小不匹配,您可能会遇到很多麻烦)。多线程也是如此。
- 您可以在 C++ 代码中使用所有您想要的异常,但是一旦它们与 C 代码交叉,所有的赌注都将关闭。
- 如果您想要更复杂的东西,您可能需要查看 PIMPL 模式。
- 当结构超出 C 代码的范围时,不会调用C++ 析构函数(某些编译器可能会承诺这样做,但这不是标准的)。如果您需要对这些对象进行任何清理,您将需要调用一个调用析构函数的外部“C”函数。
To call the destructor explicitly:
显式调用析构函数:
extern "C" void A_destroy(struct A a)
{
a.~A();
}
回答by ZelluX
I'm afraid not. But if you want to pass an object of C++ to C functions, you may refer to this link: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.8
恐怕不是。但是如果你想把 C++ 的对象传递给 C 函数,你可以参考这个链接:http: //www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.8
回答by D.Shawley
Ummm... extern "C"
forces C-style linkage. It cannot be used with classes AFAIK.
嗯……extern "C"
强制 C 型联动。它不能与 AFAIK 类一起使用。