How to extern declare an extern "C" variable - c++

I wants to export a global variable from dll I define the global variable like below. Assume this variable is defined in A.cpp
extern "C" __declspec(dllexport) int A;
Meanwhile, within the dll, another source file B.cpp wants to use and modify this value. I am wonderring how to declare the variable within B.cpp before using it.
extern "C" int A; ?
If in this case, how does compile recognize between declare and definition?
extern extern "C" int A; ?
It's definitely ill-formed.

Per [basic.def]/2.2, a declaration of an object at namespace scope is a definition unless:
it contains the extern specifier (9.2.1) or a linkage-specification19 (9.11) and neither an initializer nor a function-body,
...
19 Appearing inside the brace-enclosed declaration-seq in a linkage-specification does not affect whether a declaration is a definition.
Thus:
extern "C" int A; is a declaration.
extern "C" int A = 0; is a definition.
The below defines A and B, and declares C: the effect is the same as it would be without the extern "C" block, except that the entities declared have C linkage instead of C++ linkage.
extern "C" {
int A;
extern int B = 0;
extern int C;
}

extern extern "C" int A; ?
extern "C" can be used as a block:
extern "C"
{
extern int A;
}

The declaration needs to be in a header file like A.h or other code files cannot use it. The dllexport is especially useless without a header file. You probably want some kind of DLLEXPORT macro so you can define it to dllexport and dllimport as necessary. See pretty much any Windows DLL code.
Then in a cpp file you include the header. That allows your code to use the variable which is declared extern.
In one of your cpp files you include the header AND then define the variable using the same type and name and no extern. The linker will then put the data storage for it into the same module as the rest of that cpp file and all other uses of the name get linked to that definition.
However, just like private member variables in C++ it is a bad idea to expose global variables in a DLL. It is much better to hide access to them behind function calls.

Related

Why we should Extern "C" a struct? [duplicate]

I'm writing a C++ shared library for a C program to use. However, I have a question about extern and extern "C".
Consider the following code
My header file is like this:
#ifdef __cplusplus
extern "C" int global;
extern "C" int addnumbers(int a, int b);
#else
extern int global;
#endif
This works perfectly fine; I just have to declare
int global;
in either my .cpp or my .c file. However, what I don't understand is:
What is the difference between extern "C" and extern here? I tried commenting out extern "C" int global and it works! Why?
I know that extern "C" is used for making C linkage. That's why I have extern "C" int addnumbers(int,int). In other words, if I want to write a C++ function that is to be used in a C program, I write extern "C". Now, what about global variables - the situation is different here I guess? I want the C program to use a C++ variable named global, but I can use extern not extern "C". Why is that? This is not intuitive to me.
Comment: I don't think this is a duplicate, because I'm asking what the difference is when you use it for variables versus functions.
By attaching extern "C" to your C++ declarations (objects and functions alike) you give them "C linkage" - make them accessible from C code. If you omit this "language linkage" specification, the compiler doesn't do any effort to do proper linkage. In the case of functions, this results in failed linkage, because of mangling. In the case of global variables, everything might work fine, because variables don't need mangling.
However, on my system (MS Visual Studio), linkage between C and C++ doesn't work if I "forget" to specify the extern "C" linkage specification in the C++ header file. Example error message:
error LNK2001: unresolved external symbol "int global" (?_global)
While, when I examine a compiled C++ source code that contains the definition of global with the dumpbin utility, I see
00B 00000014 SECT4 notype External | ?global##3HA (int global)
So MS Visual Studio mangles the names of global variables, unless they have C linkage - this makes C linkage specifications mandatory.
In addition, consider the following example:
namespace example {
int global;
}
If the global variable is inside a namespace, C code will not get access to it. In this case, all compilers will require the proper linkage specification on the C++ declaration:
namespace example {
extern "C" int global;
}
Conclusion:
Use extern "C" when you want C linkage - doesn't matter if it's a function or a global variable. If it's a global variable, it may work regardless, but it's not guaranteed (and may be dangerous).
extern simply tells the compiler that the next variable(global) may not have been declared yet, but it is declared as global in a different translation unit, and during the linking stage the symbol "global" will be associated with an area in the memory.
while extern "C" is, as a few people commented, is used to solve the issue of name mangling in C++, this function will be known as addnumbers_i_i (or something similar) by the linker, while in c its symbol is addnumbers
"C++ has a special keyword to declare a function with C bindings: extern "C". A function declared as extern "C" uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as extern "C", and they cannot be overloaded."
There is no standard in C++ for function names generated by compiler. Keyword extern "C" instructs compiler to generate function name in C standard.
I find that extern "C" is used to make the C++ function compiled in C standard and it don't do with variables, for the solutions of function name in C and C++ are different. Such as "void foo( int x, int y )", C compiler will translate it into "_foo", while C++ compiler will translate it into "_foo_int_int".

extern and extern "C" for variables

I'm writing a C++ shared library for a C program to use. However, I have a question about extern and extern "C".
Consider the following code
My header file is like this:
#ifdef __cplusplus
extern "C" int global;
extern "C" int addnumbers(int a, int b);
#else
extern int global;
#endif
This works perfectly fine; I just have to declare
int global;
in either my .cpp or my .c file. However, what I don't understand is:
What is the difference between extern "C" and extern here? I tried commenting out extern "C" int global and it works! Why?
I know that extern "C" is used for making C linkage. That's why I have extern "C" int addnumbers(int,int). In other words, if I want to write a C++ function that is to be used in a C program, I write extern "C". Now, what about global variables - the situation is different here I guess? I want the C program to use a C++ variable named global, but I can use extern not extern "C". Why is that? This is not intuitive to me.
Comment: I don't think this is a duplicate, because I'm asking what the difference is when you use it for variables versus functions.
By attaching extern "C" to your C++ declarations (objects and functions alike) you give them "C linkage" - make them accessible from C code. If you omit this "language linkage" specification, the compiler doesn't do any effort to do proper linkage. In the case of functions, this results in failed linkage, because of mangling. In the case of global variables, everything might work fine, because variables don't need mangling.
However, on my system (MS Visual Studio), linkage between C and C++ doesn't work if I "forget" to specify the extern "C" linkage specification in the C++ header file. Example error message:
error LNK2001: unresolved external symbol "int global" (?_global)
While, when I examine a compiled C++ source code that contains the definition of global with the dumpbin utility, I see
00B 00000014 SECT4 notype External | ?global##3HA (int global)
So MS Visual Studio mangles the names of global variables, unless they have C linkage - this makes C linkage specifications mandatory.
In addition, consider the following example:
namespace example {
int global;
}
If the global variable is inside a namespace, C code will not get access to it. In this case, all compilers will require the proper linkage specification on the C++ declaration:
namespace example {
extern "C" int global;
}
Conclusion:
Use extern "C" when you want C linkage - doesn't matter if it's a function or a global variable. If it's a global variable, it may work regardless, but it's not guaranteed (and may be dangerous).
extern simply tells the compiler that the next variable(global) may not have been declared yet, but it is declared as global in a different translation unit, and during the linking stage the symbol "global" will be associated with an area in the memory.
while extern "C" is, as a few people commented, is used to solve the issue of name mangling in C++, this function will be known as addnumbers_i_i (or something similar) by the linker, while in c its symbol is addnumbers
"C++ has a special keyword to declare a function with C bindings: extern "C". A function declared as extern "C" uses the function name as symbol name, just as a C function. For that reason, only non-member functions can be declared as extern "C", and they cannot be overloaded."
There is no standard in C++ for function names generated by compiler. Keyword extern "C" instructs compiler to generate function name in C standard.
I find that extern "C" is used to make the C++ function compiled in C standard and it don't do with variables, for the solutions of function name in C and C++ are different. Such as "void foo( int x, int y )", C compiler will translate it into "_foo", while C++ compiler will translate it into "_foo_int_int".

Is extern keyword required here, const in cpp file

If I have in header file
namespace Bob
{
extern const T x;
};
And in source file
extern const T Bob::x = 123;
Is the second extern in the source file required or optional?
I've searched and found conflicting information.
From this webpage:
http://msdn.microsoft.com/en-us/library/357syhfh.aspx
But to get the same behavior in C++, you must declare your const variable [in source file] as:
extern const int i = 2;
Usually, the extern keyword tells the compiler not to define a symbol, because it will be defined somewhere else. So writing e.g.
namespace Bob {
extern T x;
}
does not define the variable x, but rather declares it. You can have as many extern declarations as you like. However, if you do not provide a definition the linking will fail. So you have to define
T Bob::x;
somewhere in the code in order to provide the definition.
The const keyword is a little special here, because it implies internal linkage. This means, that the definition of x will not be visible outside the specific compilation unit where it was defined. To alter this behavior you do need to write
extern const T Bob::x = 123;
if you want x to be const and also reference it from other compilation units.
----yet another edit----
Just to be absolutely clear:
If a const variable is supposed to be referenced outside of its compilation unit, then you must explicitly declare it extern.
However, if the declaration is given separately from the definition, then the definition does not necessarily need to specify the keyword extern again. Yet another example for demonstration:
myheader.h
extern const int i;
This declares i a const integer with external linkage, but does not define it.
main.cpp, version 1
#include "myheader.h" //Through the include, the above declaration of `i` comes before its definition.
const int i=123; // Although the `extern` modifier is omitted here,
// it's still in effect because we already declared `i` as `extern`
// Therefore it makes no difference here, whether or not you specify `extern` again.
// The compiler knows this is a definition either way, because of the initialization.
main.cpp, version 2
//#include "myheader.h"
extern const int i=123; // this line is declaration and definition in one, because we did not include
// the declaration from myheader.h. Thus, to tell the compiler that you want
// `i` with external linkage, you MUST specify `extern`. Otherwise you'll get
// internal linkage.
I hope all this now makes sense to you.
You can control the linkage of a symbol with the static and extern keywords. The default linkage is extern for non-const symbols and static (i.e. internal) for const symbols at namespace scope. This is valid for C++ but not for C (where you would have to declare it as static to make it have internal linkage).
So if you have
const int i = 2;
into a .c file and you use it into another unit by declaring
extern const int i;
that's fine in C since that variable has external linkage by default (and with the extern keyword you're instructing the compiler to find it into another unit), but in C++ the same
const int i = 2;
into a .cpp file (firmstanding what I wrote) has internal linkage and it would have to be defined with
extern const int i = 2;
to explicitly have external linkage and be able to be used into another unit with
extern const int i;
Finally when you initialize a global variable you're always defining it in the module where you're doing it, this means that the following is perfectly valid:
#include <iostream>
using namespace std;
#define T int
extern const T x; // This is a declaration
extern const T x = 123; // This is a definition
int main() {
std::cout << x; // 123
return 0;
}
That means the second 'extern' keyword is also unnecessary.

Extern functions in C vs C++

In *.h header files of a C library, should one declare functions
extern void f();
// or only
void f();
when using only in C
when using from C++.
There's [almost] never any need to use the keyword extern when declaring a function, either in C or in C++. In C and in C++ all functions have external linkage by default. The strange habit of declaring functions in header files with extern probably has some historical roots, but it has been completely irrelevant for decades already.
There's one [obscure?] exception from the above in C, which is probably not directly related to what you are asking about: in C language (C99) if in some translation unit a function is defined as inline and also declared as extern (an explicit extern is used) then the inline definition of that function also serves as an external definition. If no declarations with explicit extern are present in the translation unit, then the inline definition is used as "internal" definition only.
P.S. There's such thing as extern "C" in C++, but that is a completely different matter.
In header files of a C library, should one declare functions:
extern void f();
// or only
void f();
Issue 1: Semantics
In a C++ program, the functions are declared as functions returning no value and taking no arguments.
In a C program, the functions are declared as functions returning no value and taking an indeterminate but not variable-length list of arguments.
To get the 'no arguments' meaning in C, use one of:
extern void f(void);
void f(void);
The same notation also means the same thing in C++, though for pure C++ code, using void in the argument list is not idiomatic (do not do it in pure C++ code).
Issue 2: Inter-working between C and C++
Tricky, but the normal rule would that you should declare the functions to C++ code as extern "C". To use the same source code for both, you then need to test the __cplusplus macro. You'd normally do something like:
#ifdef __cplusplus
#define EXTERN_C extern "C"
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C /* Nothing */
#define EXTERN_C_BEGIN /* Nothing */
#define EXTERN_C_END /* Nothing */
#endif
EXTERN_C void f(void);
EXTERN_C_BEGIN
void f(void);
int g(int);
EXTERN_C_END
The options and variations are manifold, but the header can be used by both C and C++.
The macros would normally be defined in one general-purpose header that's used everywhere, and then the particular header would ensure that the general purpose header is included and then use the appropriate form of the macro.
Issue 3: Style
Formally, there is no need for the extern notation before a function declaration. However, I use it in headers to emphasize that it is a declaration of an externally defined function, and for symmetry with those (rare) occasions when there is a global variable declared in the header.
People can, and do, disagree over this; I go with the local rules — but when I'm the rule-maker, the extern is included in a header.
For general use declare as
#ifdef __cplusplus
extern "C" {
#endif
void f(void);
#ifdef __cplusplus
}
#endif
Otherwise, extern is obsolete.
The latter is perfectly fine, since it's only a function definition, which tells those, who include this header: 'There's a function with this prototype somewhere around here'
In this context, functions differ clearly from variables, but that's a different matter.
Make sure though, that you do not include the function body, unless you declare it 'inline' or as part of a class definition (C++) or as a 'template function' (also C++).
Specifying extern in function prototype has no effect, since it is assumed by default. Whenever a compiler sees a prototype, it assumes a function is defined somewhere else (in the current or another translation unit). This holds for both of the languages.
The following thread has some useful comments in general about extern.
Effects of the extern keyword on C functions

What is "extern linkage and with C language linkage"

What does the author mean about "extern linkage" and "C language linkage" in the following paragraph, extracted from [1].
"There are two different forms of the extern C declaration: extern C as used above, and extern C { … } with the declarations between the braces. The first (inline) form is a declaration with extern linkage and with C language linkage; the second only affects language linkage. The following two declarations are thus equivalent:"
Can you further elaborate what he's trying to explain with this example?
[1] http://tldp.org/HOWTO/C++-dlopen/thesolution.html
What the author is saying relates to these two lines:
extern "C" int foo;
extern "C" { int bar; }
foo is a variable declared but not defined. It exists elsewhere. On the other hand, bar is both declared and defined.
Think of a declaration as just stating that something exists somewhere but not actually creating it. Definition is therefore declaration plus bringing that thing into existence.
The latter one is exactly the same as int bar; but will "publish" the variable with C linkage. For example, a function int max (int a, int b); may be published as _max in C language linkage and _max$$int$int in C++ language linkage (to allow more than one function with the same name).
Note that "publishing" in this context is how the function looks to the linker, so that your code can link to it. Without C language linkage, it's usually rather difficult to link C code with C++ libraries.
Clumsy wording, yeah. What he's trying to get at is,
extern "C" int foo();
is the same as
extern "C" { extern int foo(); }
but not the same as
extern "C" { int foo(); }
... except that there is no practical difference between "extern int foo();" and "int foo();" at file scope in C++, so you are entirely forgiven for scratching your head. Here's a case where it actually makes a difference:
extern "C" const int x = 12;
extern "C" { const int y = 12; }
x will be visible outside the translation unit, y won't.