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.
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 create a Commons.h file where I can put some shared info, constants, macros and helper functions.
This file has to be included in many part of my application.
If I create function with this syntax I get a Duplicate Symbol error:
int myFunction(int a){
//do something..
}
While if I add the static keyword I get no errors.
static int myFunction(int a){
//do something..
}
1) Is this a valid/right way to add helper functions to a project?
2) What happen exactly adding the static keyword at that definition?
Not really. You're creating a separate instance of the function
in every translation unit. What you should do is only declare
the function in the header:
extern int myFunction( int a );
and define it in a source file somewhere. (Note that the
extern above is optional, since it is implicit for all
function declarations, and it is usual to omit it. I add it
here only to stress the fact that you are declaring, and not
defining.)
If you use the keyword static before a function declaration, then you only can use this function inside the actual translation unit (.cpp, .c or .m), where it was defined.
So it is the opposite of the keyword extern, extern is the default storage class specifier for functions.
The use for a helper function is then wrong, because it doesn't even compile.
Instead you should declare the function in the helper file as extern. And use it without implementing it again. You can implement it once in the .c/.cpp/.m of the helper .h.
If you use a function as a helper function for other files, then it is good practice to use the extern keyword, even though it is not needed. It is a hint for programmers, this function is used somewhere else.
As we know that we can use c functions directly in c++, when is extern "C" necessary then?
If your function is implemented in a .c file, the .cpp files will need the extern "C" reference, or else they'd reference a mangled C++-style function name, and the link would fail.
It's also handy for exporting functions from DLLs so that they are exported with a non-mangled name.
It's necessary when a C++ function must be called by C code rather than C++ code.
Basically, when you want your C++ library to be backwards compatible.
There are two rather different uses for extern "C". One is to define a function in C++ that you should be able to call from C. I.e., you're writing code in C++, but it needs to interface with C code. In this case, you define the function as extern "C":
extern "C" {
int c_callable_func1() {}
int c_callable_func2() {}
}
When you do this, the interface of those functions must follow pretty much the same rules as they would in C as well (e.g., you can't overload the functions or use default values for any parameters).
The other (considerably more common) situation is that you have code written in C that you want to be able to call from C++. In this case, the function definitions remain exactly as before, but the functions need to be declared/prototyped as extern "C". In a typical case, you want to use a single header that can be #included in either a C or C++ file, so the structure looks something like this:
// myheader.h
#ifndef MY_HEADER_H_INCLUDED_
#define MY_HEADER_H_INCLUDED_
#ifdef __cplusplus
extern "C" {
#endif
int func1(void);
void func2(int);
#ifdef __cplusplus
}
#endif
#endif
So, a C++ compiler will see function declarations (and typedefs, etc.) surrounded by an extern "C" block, while a C compiler will see prototypes, not surrounded by something it doesn't recognize.
In the first case (C++ functions callable from C), you'll normally structure the header roughly the same way, so you can also call those functions from C++ if necessary (but at the interface, you still lose all extra features of C++ like function overloading).
As you know that c++ support function overloading, which define the same function or method many times with different parameters. To do this, the compiler has to add some part of symbols for each one ... for example, the compiler will change the function name foo in the following declaration
from
void foo(int f,char c);
to
foo#i&c
Unfortunately, C doesn't support this. All function names remain the same after compiling it. So, to call a c++ function from c, you have to know the exact name after the modification and I think it's hard and different from a compiler to another.
to work around this and be able call c++ function from c and stop the compiler from changing the names you have to use this keyword like
extern "C" {
void foo(int f,char c);
}
that's it !!!
Because the function signatures generated by C and C++ compilers differ -- this sets up the C convention for C function even when using C++.
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.
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.