What is the difference between a static member function and an extern "C" linkage function ? For instance, when using "makecontext" in C++, I need to pass a pointer to function. Google recommends using extern "C" linkage for it, because "makecontext" is C. But I found out that using static works as well. Am I just lucky or...
class X {
public:
static void proxy(int i) {}
}
makecontext(..., (void (*)(void)) X::proxy, ...);
vs
extern "C" void proxy(int i) {}
makecontext(..., (void (*)(void)) proxy, ...);
EDIT: Can you show a compiler or architecture where the static member version does not work (and it's not a bug in the compiler) ?
Yes, you are just lucky :) The extern "C" is one language linkage for the C language that every C++ compiler has to support, beside extern "C++" which is the default. Compilers may supports other language linkages. GCC for example supports extern "Java" which allows interfacing with java code (though that's quite cumbersome).
extern "C" tells the compiler that your function is callable by C code. That can, but not must, include the appropriate calling convention and the appropriate C language name mangling (sometimes called "decoration") among other things depending on the implementation. If you have a static member function, the calling convention for it is the one of your C++ compiler. Often they are the same as for the C compiler of that platform - so i said you are just lucky. If you have a C API and you pass a function pointer, better always put one to a function declared with extern "C" like
extern "C" void foo() { ... }
Even though the function pointer type does not contain the linkage specification but rather looks like
void(*)(void)
The linkage is an integral part of the type - you just can't express it directly without a typedef:
extern "C" typedef void(*extern_c_funptr_t)();
The Comeau C++ compiler, in strict mode, will emit an error for example if you try to assign the address of the extern "C" function of above to a (void(*)()), beause this is a pointer to a function with C++ linkage.
Note, that extern C is the recommended way of C/C++ interoperability. Here is the master talking about it. To add to eduffy's answer: note that static functions and variables in the global namespace are deprecated. Use an anonymous namespace at least.
Back to extern C: if you don't use extern C you will have to know the exact mangled name and use it. That is much more of a pain.
extern "C" disables the C++ compiler's name mangling (which is required for overloading).
If you declare a function in A.cpp to be static, then it cannot be found by B.cpp (it's leftover from C, and it has the same effect of putting a function inside an anonymous namespace).
Most of what extern "C" does is largely compiler dependant. Many platforms change the name mangling and calling convention based off the declaration, but none of that is specified by the standard. Really the only thing the standard requires is that the code in the block is callable from C functions. As for your specific question, the standard says:
Two function types with different
language linkages are distinct types
even if they are otherwise identical.
This means extern "C" void proxy(int i) {} and /*extern "C++"*/void proxy(int i) {} have different types, and as a result pointers to these functions would have different types as well. The compiler doesn't fail your code for the same reason it wouldn't fail a great piece of work like:
int *foo = (int*)50;
makecontext(..., (void (*)(void)) foo, ...);
This code might work on some platform, but that doesn't mean it will work on another platform (even if the compiler was fully standard compliant). You are taking advantage of how your particular platform works, which might be ok if you aren't concerned about writing portable code.
As for static member functions, they aren't required to have a this pointer so the compiler is free to treat them as a non member function. Again, the behavior here is platform specific.
Generally speaking
Storage classes:
storage classes are used to indicate duration and scope of a variable or identifier.
Duration:
Duration indicates the life span of a variable.
Scope:
Scope indicates the visibility of the variable.
Static storage class:
The static storage class is used to declare an identifier that is a local variable either to a function or a file and that exists and retains its value after control passes from where it was declared. This storage class has a duration that is permanent. A variable declared of this class retains its value from one call of the function to the next. The scope is local. A variable is known only by the function it is declared within or if declared globally in a file, it is known or seen only by the functions within that file. This storage class guarantees that declaration of the variable also initializes the variable to zero or all bits off.
Extern storage class:
The extern storage class is used to declare a global variable that will be known to the functions in a file and capable of being known to all functions in a program. This storage class has a duration that is permanent. Any variable of this class retains its value until changed by another assignment. The scope is global. A variable can be known or seen by all functions within a program.
Related
Is there a difference whether I use the extern "C" specifier for the entire header, or specify extern for every function?
As far as I know, there is none, since only functions and variables can be linked externally, so when I use the extern specifier before every function prototype and extern variable, I have no need to use the global extern "C" declaration!?
Example A:
#ifdef __cplusplus
extern "C" {
#endif
void whatever(void);
#endif
Example B:
extern void whatever(void);
The presence of extern "C" in a C++ file allows to call the particular C++ function from a C client caller code.
What is the difference?
A long, long time ago C-compilers generated code and addressed functions by name only.
It didn't consider parameters.
When overloaded functions were introduced in C++, extern "C" was required to specify the same name for different functions. For example void f() and void f(int) are two different functions in C++.
The C++ compiler accomplished this via name-mangling. It adds some info to the function name related to the functions parameters.
extern "C" is a command to the compiler to "refer to the older style naming convention - without mangling".
There is a difference between those two things.
The first says "the functions in here should be compiled so as to be callable from C". C++ allows multiple functions to have the same name as long as they take different arguments. C does not. To achieve that, C++ includes argument type information in the compiled name of its functions. As a result a C compiler will not be able to find the functions. If you add an extern "C" then you instead get C behaviour, but you gain the ability to call those functions from C.
The latter says "this function exists in another compilation unit". Which means that a compiler should trust that the function with that signature exists but not worry about being unable to see it. It'll be there when you link, you promise. Declarations (contrasting with definitions) are extern by default since at least C99.
I want to implement a project in C, but it is comfortable to code some part of project in C++ and then call them from main C code.
Is it possible?! if yes, how I can do it?!
thanks in advance :)
P.S.
I used some libraries in my C++ Code such as OpenCV.
You'll need to "wrap" your C++ interface with regular C functions that take a parameter to indicate what object they'll be called on. For instance, if you have in C++
class A
{
// .. boilerplate stuff...
int SomeMethod(int n, float f);
};
Then along with it, you could declare a function such as
extern "C" int A_SomeMethod(void* Obj, int n, float f)
{
return(((A*)Obj)->SomeMethod(n, f));
}
If you're not comfortable with the casting of the void*, you can implement some kind of map from an opaque handle to an A*. But the gist is you'll need to keep around some handle/pointer to the object that the method will be called on. In order to get the pointer/handle you'll need to wrap the allocation to:
extern "C" void* A_Instantiate()
{
return new A;
}
The C++ files should be compiled separately along with the file with the functions above. A separate include for the C compilation should include declarations of all the functions above.
EDIT: The caveats and comments below are important; to answer the question, "Yes it is possible to call C++ from C", and this is one approach. It's not a complete approach as there isn't really a mechanistic way to do it, but it's a start. Also, don't forget to create another call-through for delete, etc, etc.
Q: Can I access my C code from C++ or vice versa?
A: Yes.
1) The main thing is to use extern "C" { ...} in all your headers to denote C-only functions and data, like this:
http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B
/* Header file foo.h */
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
/* These functions get C linkage */
void foo();
struct bar { /* ... */ };
#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
}
#endif
2) The usual scenario is a C++ main program that calls a mix of C and C++ functions and structs. The structs and functions are all declared in headers, and all have "#ifdef __cplusplus/extern C".
3) Here is a good FAQ on mixing C and C++:
http://www.parashift.com/c++-faq/mixing-c-and-cpp.html
Unless strictly required, this is only for dyied-in-the-wool masochists. Doing it will require extreme care on both sides, and could well work today and explode spectacularly with the next compiler update. C++ requires a lot of runtime help, and getting that to work reliably from C isn't normally supported. You can call into C from C++, that is officially supported (and part of the standard, extern "C" and such).
Probably the best bet is to write your C in the subset handled by C and C++ (a starting point on the subtle differences is this) and compile with the C++ compiler. Or get over it and decide what language you like most.
yes, you need to specify it as
extern "C"
this way it will make the function to have "C" linkage, then C code can call your function just as if it was in C. This function name will not be mangled then because C doesn't support overloading.
here let me cite #Faisal Vali:
extern "C" is a linkage-specification
Every compiler is required to provide "C" linkage
a linkage specification shall occur only in namespace scope
all function types, function names and variable names have a language linkage
two function types with distinct language linkages are distinct types even if otherwise identical
linkage specs nest, inner one determines the final linkage
extern "C" is ignored for class members
at most one function with a particular name can have "C" linkage (regardless of namespace)
extern "C" forces a function to have external linkage (cannot make it static)
Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved
see Faisal Vali answer here
EXTERN(void) jpeg_fdct_8x4
JPP((DCTELEM * data, JSAMPARRAY sample_data, JDIMENSION start_col));
Here, I had four questions:
What does the syntax Extern(Void) mean? That the return value is void? Is it a usual syntax?
I see in a third-party code non-class member functions with the static keyword, inline keyword, no keyword and extern keyword. I understand that static keyword limits the scope of the function to the file. What happens if I use "no keyword"? Do I have to use extern in other file to use that function or I can call the function directly from another file after specifying the function declaration?
Do I need extern in C++ only to call interface with C?
What is the default scope of inline functions?
EXTERN(n) is a preprocessor definition, to be found in jmorecfg.h:
#define EXTERN(type) extern type
So the above statement expands to
extern void ...
For a writeup of extern in C code, check out this answer.
What happens if I use "no keyword"?
In this case the scope is not limited. Non static, global functions have their name visible to the linker across all compilation units, which means you get name clashes if different modules use the same function names.
3) Do I need extern in C++ only to call interface with C?
You presumably refer to extern "C" {} which instructs the compiler to use C calling convention. Yes, you need this to invoke external C functions from C++.
4) What is the default scope of inline functions?
The same scope as if they weren't declared inline.
C++ is a case-sensitive language. The "extern" keyword is not the same as "EXTERN". It seems to be initializing a void function.
You can use functions from other source files without using the extern keyword. e.g. When you are writing a project, the IDE will always start debugging and compiling with the main() function. You can declare and call functions in other files without using extern.
I am just trying to further understand extern C functions.
According to my knowledge, an extern C function is always a function you are trying call from an application that has already been compiled. Either a executable, static or dynamic library.
extern "C"
{
HRESULT CreateDevice();
typedef HRESULT (*CREATEDEVICE)();
HRESULT ReleaseDevice();
typedef HRESULT (*RELEASEDEVICE)();
}
So my question is...
Is my understanding correct ??
Does it always have to be a C function pointer ??'
Why must you use a typedef for each function ??
I presume that when you use the GetProcAddress(). You are allocating memory on that particulars applications HEAP and not the one you are calling it from. Therefore you must release it from that heap as well ??
extern "C" has 2 implications. First, it declares that the symbolic names of the functions are not "name mangled" to support C++. Second, it tells the compiler that the function is called using the C calling convention rather than the PASCAL calling convention. The difference has to do with when the return address is pushed on the stack. Using the wrong calling convention will crash your app.
This declaration is for the compiler, not the linker. So the extern C function could exist in your own modules or in a binary library: the source of actual bytes for the function implementation are resolved by the linker. If the function signature is declared as a regular C++ function and not extern C, the compiler will mangle the symbolic name to encode type information from the function signature. This will make it incompatible with object code generated by other C++ compilers. Therefore creating an extern C function allows you to share code between compilers in binary form. Note that you can't expose member functions this way, only old-style C functions.
It doesn't have to be a function pointer. You can specify the function declaration normally and prefix it with extern "C", as shown in some Microsoft examples.
If you use GetProcAddress() you are not allocating any memory. You simply get the memory address of the function inside the DLL that has already been loaded into memory (with LoadLibrary(), presumably).
Even when using function pointers (such as those returned by GetProcAddress) you don't have to use typedef, it's just that the code looks pretty ugly without it. It's always hard to figure out what to write as well. I think it would be something like:
void (*pReleaseDevice)() = (void (__cdecl *)(void))GetProcAddress(hInstance, "ReleaseDevice");
extern "C" {} is a C++ convention to declare that the enclosed functions are C functions -- not C++ functions. C++ has a slightly different naming convention which conflicts with C. If you have a library written in C and want to use it in a C++ program, you have to use extern "C" {} to let the compiler know these are C functions. If the library was written in C++ I believe the extern "C" {} will cause an error.
Note that extern has multiple meanings -- this specific case is a C++ convention and is unrelated to different uses of extern. For example,
extern int count;
has a completely different meaning than extern "C" {}.
The typedef is separate from the extern "C" {} issue. typedefs let you create aliases for common types that make more sense. For example, declaring structs is often a verbose process. I can use a typedef to shorten it:
struct mystruct {int a; int b};
typedef struct mystruct returncode;
// I can now declare a variable as type 'returncode'
returncode a;
Thus, in your example the HRESULT is really an alias for (*CREATEDEVICE)() although I believe you have to put it before the function (and not after).
One important aspect of specifying extern "C" linkage is that the function names do not get mangled, which is the default for C++ names.
In order for your library's functions to be able to be loaded using GetProcAddress, you need to either add the function to the .def file, use __declspec(dllexport) or use extern "C".
To answer, in order:
extern "C" functions are used for interop with C from C++. Using them has the consequence that C code can call the function. As the windows API is a C API all functions are extern "C" to ensure that C and C++ code can make use of the API.
In order for c++ programs to interoperate with other languages, including C, as a convention , functions are exported using extern "C". Which is why a lot of dll code does this. It is not a technical requirement however.
So no, it does NOT have to be a C function pointer.
You don't have to use typedef's either.
The example code provided is from a header file that is publishing the exports of a DLL twice - Once as the set of extern "C" methods that are exported so that the dll can be statically linked. the other as a set of function pointer types, so that the dll can be dynamically loaded, and the function pointer types used with GetProcAddress.
I find such examples in Boost code.
namespace boost {
namespace {
extern "C" void *thread_proxy(void *f)
{
....
}
} // anonymous
void thread::thread_start(...)
{
...
pthread_create(something,0,&thread_proxy,something_else);
...
}
} // boost
Why do you actually need this extern "C"?
It is clear that the thread_proxy function is private internal and I do not expect that it
would be mangled as "thread_proxy" because I actually do not need it mangled at all.
In fact, in all my code that I had written and that runs on many platforms, I never used extern "C" and this had worked as-is with normal functions.
Why is extern "C" added?
My problem is that extern "C" functions pollute the global namespace and they are not actually hidden as the author expects.
This is not a duplicate!
I'm not talking about mangling and external linkage. It is obvious in this code that external linkage is unwanted!
Answer: The calling conventions of C and C++ functions are not necessarily the same, so you need to create one with the C calling convention. See 7.5 (p4) of C++ standard.
It is clear that the thread_proxy function is private internal and I do not expect that it would be mangled as "thread_proxy" because I actually do not need it mangled at all.
Regardless, it's still going to be mangled. (Had it not been extern "C") That's just how the compiler works. I agree it's conceivable a compiler could say "this doesn't necessarily need to be mangled", but the standard says nothing on it. That said, mangling doesn't come into play here, as we aren't trying to link to the function.
In fact, in all my code that I had written and that runs on many platforms, I never used extern "C" and this had worked as-is with normal functions.
Writing on different platforms has nothing to do with extern "C". I expect all standard C++ code to work on all platforms that have a standard C++ compliant compiler.
extern "C" has to do with interfacing with C, which pthread is a library of. Not only does it not mangle the name, it makes sure it's callable with the C calling convention. It's the calling convention that needs to be guaranteed, and because we can't assume we are running on a certain compiler, platform, or architecture, the best way to try and do that is with the functionality given to us: extern "C".
My problem is that extern "C" functions pollute the global namespace and they are not actually hidden as the author expects.
There's nothing polluting about the above code. It's in an unnamed namespace, and not accessible outside the translation unit.
extern "C" linkage does not necessarily mean that only name mangling is suppressed. In fact, there may be a compiler which treats extern "C" as a different calling convention.
The standard leaves this completely open as implementation-defined semantics.
The question is valid - although the function is being passed to a C library, that C library is not linking to the C++ code at all. It is only given the address of the function, so it has no interest at all in the name of the function.
The point is that extern "C" is the closest thing there is to a cross-platform way of telling the compiler to make the function use the standard C calling convention on that platform (i.e. exactly how parameters and return values should be passed on the stack).
It is unfortunate that it also has the side-effect of creating an extern linker symbol at the global level. But this could be mitigated by using a name like boost_detail_thread_proxy instead.
It's being used to make the function use whatever the compiler understands by the C calling convention while avoiding compiler specific keywords such as __cdecl.
That's all there is to it. It's got absolutely nothing to do with name mangling, namespaces or any of the other weird answers here (as you already knew when you asked).
Probably because you are interfacing a plain C library -- pthreads.
Since C and C++ are not guaranteed to have the same calling convention, you need to declare the callback function as extern "C" in order to pass it into the pthread_create C function.
The thread_proxy function above has external linkage (i.e. is visible outside its translation unit) because namespaces have no impact on extern "C" functions -- even anonymous namespaces. Instead, to give the thread_proxy function internal linkage, you need to declare it as static:
namespace boost {
namespace {
extern "C" {
static void *thread_proxy(void *f)
{
....
}
} // extern "C"
} // anonymous
...
} // boost
[Edit] Note that boost has incorporated this change. See https://svn.boost.org/trac/boost/ticket/5170.