Reputation: 642
I am working on a project in which some people have already written code in C++ and we have to use it in our code in C. So I have tried following test to write a test program which demonstrates the same:
The header file is:
#ifndef h_files_n
#define h_files_n
#include<iostream>
#ifdef __cplusplus
extern "C" {
#endif
void add_func(int, int);
#ifdef __cplusplus
}
#endif
#endif
cpp file is :
#include"h_files.h"
void add_func(int num, int nums)
{
std :: cout << "The addition of numbers is : "<< num+nums << std endl;
}
The c file is :
#include<stdio.h>
#include"h_files.h"
int main()
{
printf("We are calling the C function form C++ file.\n");
add_func(10,15);
return 0;
}
makefile is :
CC = gcc
inc = -I include
vpath %.c src
vpath %.cpp src
vpath %.o obj
all : $(addprefix obj/,functions.o main.o) run
run : main.o functions.o
$(CC) -o bin/$@ $^
obj/%.o : %.cpp
$(CXX) -c $(inc) $^ -o $@ -libstdc++
obj/%.o : %.c
$(CC) -c $(inc) $^ -o $@
.PHONY : clean
clean :
-rm -f obj/* bin/*
I am getting the following error:
g++ -c -I include src/functions.cpp -o obj/functions.o
gcc -c -I include src/main.c -o obj/main.o
gcc -o bin/run obj/main.o obj/functions.o
obj/functions.o: In function `add_func':
functions.cpp:(.text+0x1e): undefined reference to `std::cout'
functions.cpp:(.text+0x23): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)'
functions.cpp:(.text+0x2d): undefined reference to `std::ostream::operator<<(int)'
functions.cpp:(.text+0x32): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
functions.cpp:(.text+0x3a): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
obj/functions.o: In function `__static_initialization_and_destruction_0(int, int)':
functions.cpp:(.text+0x68): undefined reference to `std::ios_base::Init::Init()'
functions.cpp:(.text+0x77): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
make: *** [run] Error 1
Please somebody suggest the solution.
Upvotes: 6
Views: 412
Reputation: 1
You generally should link your C program using a C++ library with a C++ compiler (like g++
), and you very probably need to link the standard C++ library. Be (otherwise) careful about:
std::cout
) - which conceptually should be run before entering your C main
function. See also GCC function attributes, notably constructor
and visibility
attributes.new
is invoked in an out-of-memory process.struct
won't be always enough or correct, because the C++ type requires its destructor to be called, and because it may add some vtable pointer, etc...)extern "C"
Stricto sensu, C++ is designed to be interoperable with a subset of C, but not the converse.
Perhaps compiling your C code with a C++ compiler (and fixing all the incompatibilities) -e.g. with g++ -std=c++11 -Wall -Wextra -g
...- could be easier. If your C code base is small (less than 100K source lines), you could even consider porting it to C++, and progressively using C++ idiomatically. Be aware that C++11 and C11 (or C99) are different languages (which happen to have some limited and partial compatibility).
In practice, link using g++
. In almost every cases, this won't add bugs. If it does, compile all your code using g++
and rename all your C source files as C++ files (e.g. your .c
file suffix becoming .cc
) and recompile the whole thing as C++ (of course by correcting your "C" program till it makes the C++ compiler happy).
Upvotes: 2
Reputation: 182761
If I use g++ as linker then It works fine. But gcc linker gives me the problem.
That's why you should use g++
.
As I think of the problem is the function name mangling by g++ and gcc does not mangles the functions name(symbols).
When compiling C++ code, name mangling is used. When compiling C code, name mangling is not used. This has nothing to do with linking which doesn't care whether the symbols have mangled names or not.
So is there any compiler flag that would avoid name mangling if possible.
That question is based on the false assumption that name mangling has anything to do with linking.
The reason for avoiding g++ linker is It treats the linking as C++ style but the base code is in C so It may introduce some bug in calling code.
The linker doesn't care about the language the code was originally written in. It just links the compiled code.
If C code had to be linked differently from C++ code or there would be some possible bug, then what you are attempting to do would be impossible -- there would be no way to link the final executable. But since we all know C and C++ code can be linked together safely on sensible platforms like yours, you must be worried about problems that don't exist.
Upvotes: 2
Reputation: 385144
The reason for avoiding g++ linker is It treats the linking as C++ style but the base code is in C so It may introduce some bug in calling code
That's simply not true.
By the time you get to the link stage, the difference between C and C++ is largely academic: you're linking objects in machine code, not C or C++ programs.
What you do need to be aware of is calling conventions and mangled names, but if that introduces an incompatibility in your program then you'll know about it at link-time. It won't introduce silent bugs unless something is very, very wrong.
So, "it may introduce some bug in calling code" is wrong and you may go ahead and link with g++
like everybody else does. :) Because the only other difference with your C++ code is that it is referencing the standard library and C++ runtime, which you simply cannot do without.
Upvotes: 2
Reputation: 1
$(CC) -o bin/$@ $^
Use
run : main.o functions.o
$(CXX) -o bin/$@ $^
instead to link everything together using the g++
linker, and have the defaults for the linked libstc++.a
library set automatically.
Otherwise you'll need to specify -lstc++
as additional library explicitely.
Also if you're designing a pure c-API for your c++ code you should have the
#include <iostream>
statement in the functions.cpp
source file only. Remove c++ standard headers from functions.h
.
Please don't use using namespace std;
in c++ header files generally. It's prone to invoke namespace clashes of all unexpected kinds (no one knows about all of the names used in the namespace std
).
It should not appear in a pure c-API header file anyway.
If you want to have a mixed c/c++ API header file, put all of the c++ specific statements within the c++ guards:
#ifdef __cplusplus
#include<iostream>
class xyz; // A c++ forward declaration
#endif
Upvotes: 10
Reputation: 44248
You should either link program by g++
or manually specify libstdc++ library(ies).
Upvotes: 6