error with extern - undefined reference to - c++

I'm trying to compile my code, but when I do, it happens:
In function `main':
/home/emilio/CB/QAP/main.cpp|42|undefined reference to `start_timers()'
/home/emilio/CB/QAP/main.cpp|45|undefined reference to `elapsed_time()'
I have 'timer.c' and 'timer.h' as extern functions to measure time.
timer.c
#include <stdio.h>
#include <time.h>
#include "timer.h"
clock_t start_time;
double elapsed;
void start_timers(){
start_time = clock();
}
double elapsed_time( type )
TIMER_TYPE type;
{
elapsed = clock()- start_time;
return elapsed / CLOCKS_PER_SEC;
}
timer.h
extern clock_t start_time;
extern double elapsed;
int time_expired();
void start_timers();
double elapsed_time();
typedef enum type_timer {REAL, VIRTUAL} TIMER_TYPE;
main.cpp
#include "timer.h"
...
double time;
start_timers();
launch_algorithm();;
time = elapsed_time();
...
How can I fix it? Thanks!

You are mixing C and C++. To use C stuff in a C++ file, you have to wrap the header like so
#ifdef __cplusplus
extern "C"
{
#endif
extern clock_t start_time;
extern double elapsed;
int time_expired();
void start_timers();
double elapsed_time();
typedef enum type_timer {REAL, VIRTUAL} TIMER_TYPE;
#ifdef __cplusplus
}
#endif
I'm not sure how this will work with your functions, as you haven't put the parameters in the function prototypes in the header file. It is generally considered best practice to add them, so if it still doesn't work, try that.

So it seems that there are a few holes in your understanding, I will try to fill in the gaps...
The main issue is that the interoperability of C and C++.
in C having a function named dog that takes an int and returns void -> void dog(int) will be translated consistently to the object file as a symbol named something like _dog or similar (but what that symbols name is is well defined by the platform and ABI that you are using).
in C++ there is another layer of abstraction necessary by the way that they have chosen to adopt function overloading.. so our function void dog(int) could be named _void_dog_int or similar (this is called name mangling)...
so if you want to use standard C functions in a C++ program you get some strangeness...
when you write in a C++ program
dog.h (interface to some library or just C code)
void dog(int);
something.cpp
#include <doglib/dog.h>
void someMethod(void)
{
dog(4);
}
the compiler generates an object that expects dog to be named in a c++ way (_void_dog_int)
but the linker doesn't find that symbol in dog.o or libdog.a or whatever the object file is (because in the object file the symbol is named _dog like a std C program).
So there is a way to tell the C++ compiler that the symbol is a C symbol... the construct is:
extern "C" void dog(int);
or
extern "C"
{
void dog(int);
...
}
so that would fix our problems, except that it borks our C compiler!
so things have to get a little more complicated.
#ifdef __cplusplus
extern "C"
{
#endif
void dog(int);
...
#ifdef __cplusplus
}
#endif
These macros expand so that in C++ they have an extern "C", and in C they do not...
The issue with the global var is similar... C++ and std C deal with unqualified globals differently... to support namespaces or some C++ construct (I haven't looked into that specifically)

You need to make some changes to the .c and .h file; as well as the extern "C" guards.
In timer.h, the function declarations should be:
int time_expired(void);
void start_timers(void);
double elapsed_time(TIMER_TYPE type);
And in the timer.c file, those three lines should be the same (minus the semicolons).
Current you have what is known as "K&R style" function headers:
double elapsed_time( type )
TIMER_TYPE type;
{
elapsed = clock()- start_time;
return elapsed / CLOCKS_PER_SEC;
}
The problem with this sort of function header is that it does not form a prototype. The compiler will not complain in most cases if you get the list of arguments wrong. You just get undefined behaviour at runtime.
By using prototypes, the compiler will check that the function has the right number and types of arguments passed, and convert arguments if necessary.
It's conceivable that the C++ compiler will get name-mangling wrong if the functions are not prototyped.
NB. I saw in another comment you said "I changed .c by .cpp" . If you meant that you renamed timer.c to timer.cpp - don't do that! C and C++ are different languages. You should leave it as timer.c. Your compiling setup should include both a C and a C++ compiler. The C compiler compilers the C code, and the C++ compiler compiles the C++ code, with the extern "C" directives indicating how to glue the two together.

Related

how does extern "C" allow C++ code in a C file?

In order to use C++ code in a C file, I read that we can just do extern "C" { (where the c++ code goes here)}, but when I try printing something out using cout, I keep getting an error because it does not recognize the library . I think I am just confused on how extern "C" allows you to use C++ code in C.
The opposite is true. You can use extern C to add code you want to compile as C code using a C++ compiler.
Unless I'm missing something you can't compile C++ code with a C compiler.
The extern "C" construct is a C++-specific syntax, no C compiler will understand it.
That's why you will almost always see it paired with some conditional compilation like
#ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}
#endif
What extern "C" does is simply to inhibit name mangling meaning that symbols defined in a C++ source file can be used in a C program.
This allows you to have a project with mixed C and C++ sources, and the C source can call the C++ functions that have been defined as extern "C".
Very simple, and stupid, example just to show the point:
Lets say we have a C source file, compiled with a C compiler:
#include <stdio.h>
void foo(void); // Declare function prototype, so it can be called
int main(void)
{
printf("Calling foo...\n");
foo();
printf("Done\n");
return 0;
}
Then we have a C++ source file for the foo function:
#include <iostream>
extern "C" void foo()
{
std::cout << "Hello from foo\n";
}
The C source file is compiled with a C compiler, and the C++ source file is compiled with a C++ compiler. Then the two object files are linked together to form the executable program. Because foo was defined as extern "C" it's symbol name in the object file is not mangled, and the linker can resolve the reference from the object file created by the C compiler.
It works in the other direction as well. Because symbols in C are not mangled the C++ compiler needs to know that, and that is done by declaring the C symbols extern "C", usually in a header file using the conditional compilation as shown above. If extern "C" was not used, the C++ compiler would think that the symbols were C++ symbols, and mangle the names leading to linker problems when the linker can't find the mangled symbols.
Equally stupid example: First a C++ source file
#include <iostream>
extern "C" void bar(); // Declare function prototype as an unmangled symbol
int main()
{
std::cout << "Calling bar...\n";
bar();
}
Then the C source file
#include <stdio.h>
void bar(void)
{
printf("Inside bar\n");
}
extern "C" is a way of putting C code in C++ code. More specifically it tells the compiler to disable certain things like function overloading so that it can also turn off the name mangling. In C++ a simple function like:
int add(int a, int b) {
return a+b;
}
Will actually get some funky name in the library to denote the parameters so that if you define another function like:
double add(double a, double b) {
return a+b;
}
That it knows which one to call. You don't want that if you're trying to use a C library and that's what extern "C" is for. All of this being said, extern "C" does not allow C++ in a C program.
Exported C++ symbols, as generated my the compiler, are mangled to include additional type information about the symbol to the linker.
So the following overloaded functions would be distinguishable by the linker in C++, but not C:
int fn();
int fn(int);
int fn(char*);
int fn(char*) const;
int fn(const char*);
The extern "C" { ... } syntax allows symbols (or references to C symbols) to be defined in C++ code without using the mangling rules.
This allows such C++ code to be linked with C libraries.

C++ program using a C library headers is recognizing "this" as a keyword. Extern "C" error?

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.

Calling C++ functions from C file

I am quite new to C and C++. But I have some C++ functions which I need to call them from C. I made an example of what I need to do
main.c:
#include "example.h"
#include <stdio.h>
int main(){
helloWorld();
return 0;
}
example.h:
#ifndef HEADER_FILE
#define HEADER_FILE
#ifdef __cplusplus
extern "C" {
#endif
void helloWorld();
#ifdef __cplusplus
}
#endif
#endif
example.cpp:
#include <iostream.h>
void helloWorld(){
printf("hello from CPP");
}
It just doesn't work. I still receive the error of undefined reference to _helloWorld in my main.c. Where is the the problem?
Short answer:
example.cpp should include example.h.
Longer answer:
When you declare a function in C++, it has C++ linkage and calling conventions. (In practice the most important feature of this is name mangling - the process by which a C++ compiler alters the name of a symbol so that you can have functions with the same name that vary in parameter types.) extern "C" (present in your header file) is your way around it - it specifies that this is a C function, callable from C code, eg. not mangled.
You have extern "C" in your header file, which is a good start, but your C++ file is not including it and does not have extern "C" in the declaration, so it doesn't know to compile it as a C function.
the extern "C" tells C++ that the declared function has to use the C ABI (Application Binary interface), hence, whether the language is C or C++, your void HelloWorld() is always seen externally as it is C.
But you implemented it in the cpp file like it is a C++ one, C is not aware of.
You have to make the prototype of HelloWorld coherent for both C and C++, so the cpp file should declare it as extern "C" void Helloworld() { /*your code here*/ }, or simply, #include "example.h" from example.cpp, so that, before implementing it, the compiler already knows it has to follow the C convention.

Impact of using extern "C" { on C++ code when using g++

When using G++ (e.g. version 4.5 on Linux) can anyone explain what will/can happen if a user writes a header file for a mixed C/C++ system like this:
#ifdef __cplusplus
extern "C" {
int myCPPfunc(some_arg_list....); /* a C++ function */
}
#endif
but here myCPPfunc() is a normal C++ function with a class def inside - i.e. it was wrongly labeled as a C function.
What is the impact of this?
The main impact of this is that you cannot overload it, e.g. this is legal:
int myCPPfunc(int a);
int myCPPfunc(char a);
But this is not:
extern "C"
{
int myCPPfunc(int a);
int myCPPfunc(char a);
}
It is perfectly legitimate to have the implementation of an extern "C" function use arbitrary C++ features. What you can't do is have its interface be something you couldn't do in C, e.g. argument overloading, methods (virtual or otherwise), templates, etc.
Be aware that a lot of the "something you couldn't do in C" cases provoke undefined behavior rather than prompt compile errors.
This tells the C++ compiler that the functions declared in the header file are C functions.
http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.2
This is exactly what extern "C" is for - it allows you to write a C++ function that can be called from C.
Essentially, that declaration is telling the C++ compiler that you want the C++ function myCPPfunc() to have an external interface that is linkable (and therefore callable) from C.
The implementation of the function is still C++ and can still use C++ features.
Typically, the declaration of the function in the header file might look more like:
#ifdef __cplusplus
extern "C" {
#endif
int myCPPfunc(some_arg_list....); /* a C++ function */
#ifdef __cplusplus
}
#endif
That lets the same header file be used by either the C++ compiler or the C compiler, and each will see it as declaring a C callable function.

How does an extern "C" declaration work?

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