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
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.'
Syntactically, extern "C"
can be applied to either a single statement of a curly-delimited block:
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.
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).
It is possible to apply extern "C"
on functions that exist in a namespace, but the namespace information will simply disappear when used via C.
If you already have a class (we'll use a POD class for 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:
// 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
#include "try.h"
int main()
{
struct A a = A_create();
printf("%d", A_foo(a));
}
Using gcc you would compile this as follows:
g++ try.cc -c -o try.o
gcc try.c try.o
There are a few important points:
new
or delete
(or new[]
or delete[]
) you will need to link the final program to the C++ runtime library (the command line switch for this in gcc is -lstdc++
.To call the destructor explicitly:
extern "C" void A_destroy(struct A a)
{
a.~A();
}