Undefined reference, but linked and included - c++

In my Eclipse C/C++ project there is this undefined reference error which doesn't go away, doesn't matter what I do. I already changed the link order, checked if all files are compiled and included, basically everything, which is recommended in the in the Internet, when facing this problem.
Here's my program:
[...] - means that there is more code, which doesn't relate.
menulib.h
[...]
void start_GUI( void );
[...]
start_GUI.c - Note this is a .c-File
#include "menulib.h"
void start_GUI( void )
{
[...]
}
coreInterface.h
#ifndef COREINTERFACE_H_
#define COREINTERFACE_H_
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
/** only include the Core when compiled for C++ */
#include "Core.h"
#endif /* #ifdef CORE */
#ifdef __cplusplus
extern "C" {
#endif
void init_GUI( Core* core);
#ifdef __cplusplus
}
#endif
#endif /* COREINTERFACE_H_ */
coreInterface.cpp - Note this is a .cpp-File
#include "coreInterface.h"
#include "menulib.h"
void init_GUI( Core* core)
{
gui_core = core;
start_GUI(); // <--- **error appears here** - calls a .c file
}
Here's the error in the makefile (the auto generated one from Eclipse):
g++ -L/home/PC/the_Project/menu_GUI -o "the_Project" [...] ./menu_GUI/coreInterface.o [...] ./menu_GUI/start_GUI.o [...] -lcurses
./menu_GUI/coreInterface.o: In function `init_GUI':
/home/PC/the_Project/Default/../menu_GUI/coreInterface.cpp:23: undefined reference to `start_GUI()'
I believe this is coming from merging the .c and .cpp files. Still I couldn't solve it. Has anyone an idea?
Kind Regards

The problem is that you share the menulib.h header between C and C++ without specifying to C++ compiler that the function start_GUI is defined in C. Use extern "C" in #ifdef not only for init_GUI, but also for start_GUI.

Working example:
#include "coreInterface.h"
extern "C" {
#include "menulib.h"
}
void init_GUI( Core* core)
{
gui_core = core;
start_GUI();
}

Related

Undefined reference when use c-function from c++ file

I just begin new project in eclipse. Try to use C-library from C++ file.
In headers, where are prototypes of functions, here is:
#ifdef __cplusplus
extern "C" {
#endif
// prototypes...
void Init_Configuration(void);
#ifdef __cplusplus
}
#endif
It's initialize.h. In main.cpp i include this file and try use function:
#include "initialize.h"
int main()
{
Init_Configuration();
// Life cycle
while (1)
{
}
}
After compilation i get this error:
initialize.c:54: undefined reference to `SPI_Cmd'
In source C file "initialize.c", where i also include "initialize.h" i use function from C-library for stm32f2xx:
#include "initialize.h"
#include "stm32f2xx_rcc.h"
#include "stm32f2xx_spi.h"
#include "stm32f2xx_gpio.h"
// some code
SPI_Cmd(SPI1, DISABLE);
// some code
In this library also is this code:
#ifdef __cplusplus
extern "C" {
#endif
...
I don't know where a problem. Please, help!

How to use CGO for header file with conditionally inline function?

I´m currently writing a Go wrapper for C api which contains header with this ifdef:
#ifdef __cplusplus
#define TEST_INLINE inline
#else
#define TEST_INLINE
#endif
TEST_INLINE int callC_inline (){
return 1;
}
Unfortunately, I cannot change header since it's a third-party code. The code compiles fine if I pass -Wl,--allow-multiple-definition to linker, but I think it's a bad practice. So, I'm interested is there any flag I can pass to CGO or trick to satisfy #ifdef __cplusplus condition?
Compilation exception:
C:\Temp\go-build318595762\cgo_issue\_obj\lib.o: In function `callC_inline':
./lib.h:11: multiple definition of `callC_inline'
C:\Temp\go-build318595762\cgo_issue\_obj\main.cgo2.o:D:/work/go/cgo_issue/lib.h:11: first defined here
collect2.exe: error: ld returned 1 exit status
main.go:
package main
//#cgo CFLAGS: -std=gnu99
//#include "lib.h"
import "C"
import "fmt"
func main() {
fmt.Printf("Go call\n")
C.callC()
}
lib.h:
void callC();
#ifdef __cplusplus
#define TEST_INLINE inline
#else
#define TEST_INLINE
#endif
TEST_INLINE int callC_inline (){
return 1;
}
lib.c:
#include "lib.h"
#include <stdio.h>
void callC(){
printf("C call\n");
}
It is possible to pass some additional info to cgo via special comments. In this case // #cgo CFLAGS: -D__cplusplus
More info here

Linking error when Calling a C header file

I am calling a C function from a header file I wrote in Qt written in Cpp. I keep getting a linking error when I try to compile my Qt Application.
here is the header file:
#ifndef GROUND_SERVER_H
#define GROUND_SERVER_H
#ifdef __cplusplus
extern "C" {
#endif
struct system_info{
char id[33];
};
/* Support function for the below function */
void Generate_Key(char*,char*,char*);
/* Runs the actual key generation as well as
moves the file to the respectful card or
USB drive inserted in the system that will
act as the user system key */
void run_key_generation(struct system_info*,char*,char*);
/* Function to run the server on a selected
port at which the medium that the server
is to listen on will be connected. */
void run_server(unsigned short);
void generate_id();
#ifdef __cplusplus
};
#endif
#endif
#include "foo.h" is only the textual inclusion of the contents of foo.h into the current compilation unit. If you implement a function in a different file, then you need to compile that file, too, and link the resulting object files to form an executable (or library).
This does also apply when mixing C and C++ (or most other compiled) code: You compile the source code files with the compiler suitable for the language they're written in, and finally link everything together.
So:
foo.h
#ifndef FOO_H
#define FOO_H 1
#ifdef __cplusplus
extern "C" {
#endif
int answer(void);
#ifdef __cplusplus
}
#endif
#endif
foo.c
int answer(void) {
return 42;
}
bar.cc
#include <iostream>
#include "foo.h"
int main(int argc, char ** argv) {
std::cout << "The answer is " << answer() << std::endl;
return 0;
}
To create an executable from these files, you need to:
gcc -c foo.c # Compile C file
g++ -c bar.cc # Compile C++ file
g++ -o foobar foo.o bar.o # Link

Linking C compiled static library to C++ Program

I tried to link a static library (compiled with gcc) to a c++ program and I got 'undefined reference'. I used gcc and g++ version 4.6.3 on a ubuntu 12.04 server machine. For example, here is the simple library file for factorial method:
mylib.h
#ifndef __MYLIB_H_
#define __MYLIB_H_
int factorial(int n);
#endif
mylib.c
#include "mylib.h"
int factorial(int n)
{
return ((n>=1)?(n*factorial(n-1)):1);
}
I created object for this mylib.c using gcc:
gcc -o mylib.o -c mylib.c
Again the static library was created from the object file using AR utility:
ar -cvq libfact.a mylib.o
I tested this library with a C program (test.c) and C++ program (test.cpp)
Both C and C++ program have the same body:
#include "mylib.h"
int main()
{
int fact = factorial(5);
return 0;
}
Assuming static library libfact.a is available in /home/test directory, I compiled my C program without any issues:
gcc test.c -L/home/test -lfact
However while testing C++ program, it threw a link error:
g++ test.cpp -L/home/test -lfact
test.cpp:(.text+0x2f): undefined reference to `factorial(int)'
collect2: ld returned 1 exit status
I even tried adding extern command in test.cpp:
extern int factorial(int n) //added just before the main () function
Still the same error.
Can someone tell me what I am wrong here?
Is there anything I missed while creating the static library?
Do I have to add anything in my test.cpp to make it work?
The problem is that you haven't told your C++ program that factorial is written in C. You need to change your test.h header file. Like this
#ifndef __MYLIB_H_
#define __MYLIB_H_
#ifdef __cplusplus
extern "C" {
#endif
int factorial(int n);
#ifdef __cplusplus
}
#endif
#endif
Now your header file should work for both C and C++ programs. See here for details.
BTW names containing a double underscore are reserved for the compliler (so are names starting with an underscore and a capital letter) so #ifndef __MYLIB_H_ is illegal strictly speaking. I would change to #ifndef MYLIB_H #define MYLIB_H
While the accepted answer is absolutely correct, I thought I'd just add an observation. Some editors have trouble with the open / close brace, and will indent the entire extern "C" scope in the header. If mylib.h is a key header for a library, you might consider:
#if defined (__cplusplus)
#define _MYLIB_INIT_DECL extern "C" {
#define _MYLIB_FINI_DECL }
#else
#define _MYLIB_INIT_DECL
#define _MYLIB_FINI_DECL
#endif
All other headers in mylib library, e.g., mylib_aux.h, can be of the form:
#ifndef _MYLIB_AUX_H
#define _MYLIB_AUX_H
#include <mylib.h>
_MYLIB_INIT_DECL
... header content ...
_MYLIB_FINI_DECL
#endif /* _MYLIB_AUX_H */
Obviously, the names I'm using are arbitrary, but for multiple library headers, this approach has been useful to me.

Referencing C functions in static library from C++

I have a static library of functions written in C. Let's say the header file is called myHeader.h and looks like:
#ifndef MYHEADER_H
#define MYHEADER_H
void function1();
void function2();
#endif
function1 and function2 aren't anything too special. Let's say they exist in a file called impl1.c which looks like:
#include "myHeader.h"
void function1() {
// code
}
void function2() {
// more code
}
All of the code mentioned so far is compiled into some static library called libMyLib.a. I'd rather not modify any of the code used to build this library. I also have a C++ header (cppHeader.h) that looks like:
#ifndef CPPHEADER_H
#define CPPHEADER_H
class CppClass {
private:
double attr1;
public:
void function3();
};
#endif
Then cppHeader.cpp looks like:
#include "cppHeader.h"
#include "myHeader.h"
// constructor
CppClass::CppClass(){}
void CppClass::function3() {
function1();
}
When I try to compile this, I get an error about an undefined reference to function1(). I believe that I've linked everything properly when compiling. I'm pretty rusty in my C++. I'm sure that I'm just doing something stupid. I hope that my simple example code illustrates the problem well enough.
Thanks in advance for any help!
The other solution (to the one suggested originally by Yann) is to surround your "C" header with:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
Which saves you from having to remember to do:
extern "C" {
#include "foo.h"
}
every place you use foo.h
Make sure to use:
extern "C" {
#include "myHeader.h"
}
Or else the C++ compiler will generate symbol names which are name-mangled.