MyHeader.h
#ifndef __MYHEADER_H
#define __MYHEADER_H
#ifdef __cplusplus
extern "C"{
#endif
void dchar(unsigned char);
void char*(char c);
#ifdef __cplusplus
}
#endif
#endif
Errors
Declaration syntax error
Ambiguity between dchar(unsigned char) and dchar (char)
The program is on the website.
You are using C linkage in your program, this means names will not be mangled by the compiler. In your example, you declare two functions named dchar, one taking an unsigned char argument, one taking a char argument. Because of the C linkage, these will both appear to the linker using the name dchar instead of the usual mangled name. The linker cannot see the difference between these two functions, and will throw an error, since it thinks you implemented the same function twice.
Since you marked this question as C++, you could solve this by simply removing the extern "C" declaration, if you want to use these functions in C too, you will need to change the name of one function.
Related
In a file, I have this macro:
#if defined(__cplusplus)
#define EXTERN_C extern "C"
#else
#define EXTERN_C extern
#endif
But searching on the web, it doesn't seem typical for such macros to have an extern on the C path (though some examples exist). They generally come in pairs more akin to EXTERN_C_BEGIN and EXTERN_C_END to wrap up a group of declarations...and are a no-op in C builds.
But this means in a header file, you wind up having to write:
EXTERN_C_BEGIN
extern int x; /* ...but I already said extern... */
void doSomething(int y);
EXTERN_C_END
This happens because extern "C" int x; is equivalent to extern "C" { extern int x; }... not extern "C" { int x; }. The latter form only gives "C linkage", but not the historical meaning of C extern. Then if you try to make the single-line form decay in C to extern, you can't say EXTERN_C extern int x;, the compiler will complain in the C++ build at the two-externs-on-one-declaration.
Since there's no begin/end form, it's (often) going to mean more typing. But I prefer the "announcement of intent" to the compiler, even in the C case:
EXTERN_C int x;
EXTERN_C void doSomething(int y); /* does `extern` help the C case? */
I cannot offhand seem to create a good scenario where having the extern on the function declarations helps catch a mistake in C. But intuitively it seems there might be value in the redundancy, and as I say, having to do extern "C" and then later still put extern on things feels awkward.
What is the reasoning to prefer (or avoid) either approach?
Usually you see this in headers that were written for C and later made compatible with C++. The easiest way to do that is to simply wrap the whole header in extern "C" { and }. That way there's no need to touch every single declaration, and the main contents can stay plain C.
The macros you're talking about simplify this wrapping. Now it's just two lines:
EXTERN_C_BEGIN
EXTERN_C_END
Instead of the slightly more elaborate dance you'd have to do otherwise to hide the lines from the C compiler:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
The other issue is that global variables are relatively rare (compared to functions), and you don't need extern in function declarations. So there's less need for an extern macro.
If there are multiple declarations to be marked then your way ends up being more verbose than the begin/end way.
My most preferred form is the one where nothing is hidden -- someone reading the code doesn't have to go and look up what EXTERN_C is defined as in order to understand the code. With your suggestion, the reader would have to go and check whether it was extern or blank in C mode, or even something else.
Your way would work but I think a large part of it is conforming to what others reading the code will expect.
Adding 'extern' to a function declaration in a header file have no real benefits. So, the 'extern' is present in C++ versions of the macro because it is needed to tell the compiler to use C calling-convention for such functions. For a C compiler the extern can be ommited altogether.
See this answer for my details: https://stackoverflow.com/a/856736/1050181
My C++ program needs to use an external C library.
Therefore, I'm using the
extern "C"
{
#include <library_header.h>
}
syntax for every module I need to use.
It worked fine until now.
A module is using the this name for some variables in one of its header file.
The C library itself is compiling fine because, from what I know, this has never been a keyword in C.
But despite my usage of the extern "C" syntax,
I'm getting errors from my C++ program when I include that header file.
If I rename every this in that C library header file with something like _this,
everything seems to work fine.
The question is:
Shouldn't the extern "C" syntax be enough for backward compatibility,
at least at syntax level, for an header file?
Is this an issue with the compiler?
Shouldn't the extern "C" syntax be enough for backward compatibility, at least at syntax level, for an header file? Is this an issue with the compiler?
No. Extern "C" is for linking - specifically the policy used for generated symbol names ("name mangling") and the calling convention (what assembly will be generated to call an API and stack parameter values) - not compilation.
The problem you have is not limited to the this keyword. In our current code base, we are porting some code to C++ and we have constructs like these:
struct Something {
char *value;
char class[20]; // <-- bad bad code!
};
This works fine in C code, but (like you) we are forced to rename to be able to compile as C++.
Strangely enough, many compilers don't forcibly disallow keyword redefinition through the preprocessor:
#include <iostream>
// temporary redefinition to compile code abusing the "this" keyword
#define cppThis this
#define this thisFunction
int this() {
return 1020;
}
int that() {
return this();
}
// put the C++ definition back so you can use it
#undef this
#define this cppThis
struct DumpThat {
int dump() {
std::cout << that();
}
DumpThat() {
this->dump();
}
};
int main ()
{
DumpThat dt;
}
So if you're up against a wall, that could let you compile a file written to C assumptions that you cannot change.
It will not--however--allow you to get a linker name of "this". There might be linkers that let you do some kind of remapping of names to help avoid collisions. A side-effect of that might be they allow you to say thisFunction -> this, and not have a problem with the right hand side of the mapping being a keyword.
In any case...the better answer if you can change it is...change it!
If extern "C" allowed you to use C++ keywords as symbols, the compiler would have to resolve them somehow outside of the extern "C" sections. For example:
extern "C" {
int * this; //global variable
typedef int class;
}
int MyClass::MyFunction() { return *this; } //what does this mean?
//MyClass could have a cast operator
class MyOtherClass; //forward declaration or a typedef'ed int?
Could you be more explicit about "using the this name for some variables in one of its header files"?
Is it really a variable or is it a parameter in a function prototype?
If it is the latter, you don't have a real problem because C (and C++) prototypes identify parameters by position (and type) and the names are optional. You could have a different version of the prototype, eg:
#ifdef __cplusplus
extern "C" {
void aFunc(int);
}
#else
void aFunc(int this);
#endif
Remember there is nothing magic about header files - they just provide code which is lexically included in at the point of #include - as if you copied and pasted them in.
So you can have your own copy of a library header which does tricks like the above, just becoming a maintenance issue to ensure you track what happens in the original header. If this was likely to become an issue, add a script as a build step which runs a diff against the original and ensures the only point of difference is your workaround code.
I have a mix of C C++ code. All compiled with g++. Wherever I have C headers I have the contents of the header file included inside
#if defined(__cplusplus)
extern "C" {
#endif
and
#if defined(__cplusplus)
extern "C" {
#endif
But in one C header file I get g++ compilation errors where I have accidentally used a parameter name as template , which obviously is incorrect and in conflict with c++ keyword template.
I know I can go and change this parameter name, but I am thinking why is this extern "C" declaration not working and why is the header file considered as C++ code and not C as I intended to.
g++ version 4.1.1 Linux Red Hat Enterprise.
The extern "C" only tells the compiler (actually, the linker) that C++ name mangling doesn't apply to the functions declared in that scope. It has nothing to do with the syntax or keywords themselves.
Your best solution is to rename the conflicting symbols.
Consider:
extern "C" {
namespace n
{
int& foo(bool b)
{
if (!b)
throw std::invalid_argument("fail!");
static int i = 0;
return ++i;
}
}
}
This function has C language linkage, but uses references, namespaces and exceptions, which I hope demonstrates that extern "C" doesn't magically switch the compiler to compiling C, it just tells the compiler to use C calling conventions and symbol-naming conventions for the functions and variables with C language linkage (which usually just means it disables name-mangling and causes matching declarations in different namespaces to refer to the same entity.)
I want to use some c++ classes in shared library with C linkage. And i got following problems.
If
#include <iostream>
extern "C"
{
void f(){}
}
Compiles and links succesfully, but f() could not be found in resulting library.
If
extern "C"
{
#include <iostream>
void f(){}
}
I got many compiler errors (just dont know how to correctly translate them in english, something about template with C linkage) on every occurence of C++ keyword "template" in iostream and included headers.
What should be done?
The first variant is correct. Only stuff that even exists in C can be declared in a extern "C" block, and templates and classes certainly don't belong in that category. You only have to make sure, that your function is also declared as extern "C" in the header if you are using a C++-compiler. This is often achieved by writing
#ifdef __cplusplus
// C++ declarations (for example classes or functions that have C++ objects
// as parameters)
extern "C"
{
#endif
// C declarations (for example your function f)
#ifdef __cplusplus
}
#endif
in the header.
The first is correct; system headers (and most other headers as well)
can only be included at global scope, outside any namespaces, classes,
functions or linkage specification blocks. There are likely things in
<iostream> that wouldn't be legal in an extern "C", and even if
there weren't, the name mangling for extern "C" is almost certainly
different from that of C++, and the library itself was surely compiled
as extern "C++".
How did you define f? This could be a similar problem: if the source
file compiles it as an extern "C++" function, then the name will be
mangled differently than it was in the client files which compiled it as
an extern "C" function.
The general policy here is to handle the headers and the function
definitions/declarations in the same way you normally do, except that
you ensure that the header can be included in both C and C++ sources,
e.g.:
#if __cplusplus
extern "C" {
#endif
void f();
// Other `extern "C"` functions...
#if __cplusplus
}
#endif
Then include this header in all files where the function f() is used,
and in the file where it is defined.
Use __declspec to export functions, classes, etc...
Also: http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx
And this one is very good: http://www.flounder.com/ultimateheaderfile.htm
I'm taking a programming languages course and we're talking about the extern "C" declaration.
How does this declaration work at a deeper level other than "it interfaces C and C++"? How does this affect the bindings that take place in the program as well?
extern "C" is used to ensure that the symbols following are not mangled (decorated).
Example:
Let's say we have the following code in a file called test.cpp:
extern "C" {
int foo() {
return 1;
}
}
int bar() {
return 1;
}
If you run gcc -c test.cpp -o test.o
Take a look at the symbols names:
00000010 T _Z3barv
00000000 T foo
foo() keeps its name.
Let's look at a typical function that can compile in both C and C++:
int Add (int a, int b)
{
return a+b;
}
Now in C the function is called "_Add" internally. Whereas the C++ function is called something completely different internally using a system called name-mangling. Its basically a way to name a function so that the same function with different parameters has a different internal name.
So if Add() is defined in add.c, and you have the prototype in add.h you will get a problem if you try to include add.h in a C++ file. Because the C++ code is looking for a function with a name different to the one in add.c you will get a linker error. To get around that problem you must include add.c by this method:
extern "C"
{
#include "add.h"
}
Now the C++ code will link with _Add instead of the C++ name mangled version.
That's one of the uses of the expression. Bottom line, if you need to compile code that is strictly C in a C++ program (via an include statement or some other means) you need to wrap it with a extern "C" { ... } declaration.
When you flag a block of code with extern "C", you're telling the system to use C style linkage.
This, mainly, affects the way the linker mangles the names. Instead of using C++ style name mangling (which is more complex to support operator overloads), you get the standard C-style naming out of the linker.
It should be noted that extern "C" also modifies the types of functions. It does not only modify things on lower levels:
extern "C" typedef void (*function_ptr_t)();
void foo();
int main() { function_ptr_t fptr = &foo; } // error!
The type of &foo does not equal the type that the typedef designates (although the code is accepted by some, but not all compilers).
extern C affects name mangling by the C++ compiler. Its a way of getting the C++ compiler to not mangle names, or rather to mangle them in the same way that a C compiler would. This is the way it interfaces C and C++.
As an example:
extern "C" void foo(int i);
will allow the function to be implemented in a C module, but allow it to be called from a C++ module.
The trouble comes when trying to get a C module to call a C++ function (obviously C can't use C++ classes) defined in a C++ module. The C compiler doesn't like extern "C".
So you need to use this:
#ifdef __cplusplus
extern "C" {
#endif
void foo(int i);
#ifdef __cplusplus
}
#endif
Now when this appears in a header file, both the C and C++ compilers will be happy with the declaration and it could now be defined in either a C or C++ module, and can be called by both C and C++ code.
In C++ the name/symbol of the functions are actually renamed to something else such that different classes/namespaces can have functions of same signatures. In C, the functions are all globally defined and no such customized renaming process is needed.
To make C++ and C talk with each other, "extern C" instructs the compiler not to use the C convention.
extern "C" denotes that the enclosed code uses C-style linking and name mangling. C++ uses a more complex name mangling format. Here's an example:
http://en.wikipedia.org/wiki/Name_mangling
int example(int alpha, char beta);
in C: _example
in C++: __Z7exampleic
Update: As GManNickG notes in the comments, the pattern of name mangling is compiler dependent.
extern "C", is a keyword to declare a function with C bindings, because C compiler and C++ compiler will translate source into different form in object file:
For example, a code snippet is as follows:
int _cdecl func1(void) {return 0}
int _stdcall func2(int) {return 0}
int _fastcall func3(void) {return 1}
32-bit C compilers will translate the code in the form as follows:
_func1
_func2#4
#func3#4
in the cdecl, func1 will translate as '_name'
in the stdcall, func2 will translate as '_name#X'
in the fastcall, func2 will translate as '#name#X'
'X' means the how many bytes of the parameters in parameter list.
64-bit convention on Windows has no leading underscore
In C++, classes, templates, namespaces and operator overloading are introduced, since it is not allowed two functions with the same name, C++ compiler provide the type information in the symbol name,
for example, a code snippet is as follows:
int func(void) {return 1;}
int func(int) {return 0;}
int func_call(void) {int m=func(), n=func(0);}
C++ compiler will translate the code as follows:
int func_v(void) {return 1;}
int func_i(int) {return 0;}
int func_call(void) {int m=_func_v(), n=_func_i(0);}
'_v' and '_i' are type information of 'void' and 'int'
Here is a quote from msdn
"The extern keyword declares a variable or function and specifies that it has external linkage (its name is visible from files other than the one in which it's defined). When modifying a variable, extern specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends). The variable or function may be defined in another source file, or later in the same file. Declarations of variables and functions at file scope are external by default."
http://msdn.microsoft.com/en-us/library/0603949d%28VS.80%29.aspx