只是想确认在 Windows 环境下,VSTS 2008 + C++ 项目,我们只能将 extern C 应用到函数级别,不能应用到类级别(以便类中的所有成员函数都使用 C 语言名称修饰)?我尝试了几种方法,但总是编译错误。
提前谢谢,乔治
只是想确认在 Windows 环境下,VSTS 2008 + C++ 项目,我们只能将 extern C 应用到函数级别,不能应用到类级别(以便类中的所有成员函数都使用 C 语言名称修饰)?我尝试了几种方法,但总是编译错误。
提前谢谢,乔治
您可以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
根据 ISO C++03 9.3[class.mfct]/9,这是可能的:
可以使用函数类型的 typedef 声明(但未定义)成员函数。结果成员函数的类型与显式提供函数声明符时的类型完全相同,请参见 8.3.5。
但是,由于 ISO C++03 7.5[dcl.link]/4,这并不能真正为您买任何东西:
对于类成员的名称和类成员函数的成员函数类型,AC 语言链接被忽略。
extern "c" 使用 c 风格的链接;也就是说,原始函数名是从库中公开的。因为它只是一个原始函数名称,所以没有任何 C++ 独有的功能可以使用它,包括名称空间、类、结构或联合中的方法或外部数据成员。
澄清:结构和联合在 C 中,但没有成员函数,因此它们在 C++ 中的成员函数不能以 c 样式导出(结构和联合定义不需要导出,因为它已经在标题中)
查看您对先前答案的评论(“[M]y 的问题是我们是否可以extern C
在类级别应用,以便类中的所有函数自动具有 C 样式名称修饰?”,答案是 'extern "C"
不完全那样工作。
从语法上讲,extern "C"
可以应用于花括号分隔块的单个语句:
extern "C" int my_foo(int i)
{
...
}
extern "C" {
int my_bar(int i)
{
...
}
int my_baz(int i)
{
...
}
}
在整个 C 头文件上使用extern "C"
适当的保护是很常见的。#ifdef __cplusplus
从语义上讲,应用的实际效果extern "C"
只适用于“普通”(即非类)函数和函数指针。当然,您不能将其应用于 C++ 模板。您也不能将它应用于类方法(因为类方法需要知道调用了哪个对象,而 C 样式的链接没有任何方法可以将该信息传递给函数)。
可以应用于命名空间中extern "C"
存在的函数,但命名空间信息在通过 C 使用时会简单地消失。
如果您已经有一个类(为简单起见,我们将使用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));
}
使用 gcc 你可以编译如下:
g++ try.cc -c -o try.o
gcc try.c try.o
有几点很重要:
new
or delete
(or new[]
or delete[]
),您将需要将最终程序链接到 C++ 运行时库(gcc 中的命令行开关是-lstdc++
.显式调用析构函数:
extern "C" void A_destroy(struct A a)
{
a.~A();
}
恐怕不是。但是如果你想将 C++ 的对象传递给 C 函数,你可以参考这个链接: http: //www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.8
嗯...extern "C"
强制 C 样式的链接。它不能与 AFAIK 类一起使用。