Compiling and linking C code invoking C++ function - c++

I have a problem when invoking a C++ method from my C code. The method I need to invoke in the C++ code is not within a class. I am trying to setup a simple example and I have the following files:
//header.h
#ifdef __cplusplus
#include <iostream>
extern "C" {
#endif
int print(int i, double d);
#ifdef __cplusplus
}
#endif
//ccode.c
#include "header.h"
main() {
printf("hello");
print(2,2.3);
}
//cppcode.cc
#include "header.h"
using namespace std;
int print(int i, double d)
{
cout << "i = " << i << ", d = " << d;
}
Probably my error is in the way I am trying to compile and link this. I am doing the following:
g++ -c cppcode.cc -o cppcode.o
That goes fine.
gcc ccode.c cppcode.o -o ccode
Here I get the following errors:
cppcode.o: In function `print':
cppcode.cc:(.text+0x16): undefined reference to `std::cout'
cppcode.cc:(.text+0x1b): 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*)'
cppcode.cc:(.text+0x28): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(int)'
cppcode.cc:(.text+0x35): 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*)'
cppcode.cc:(.text+0x42): undefined reference to `std::basic_ostream<char, std::char_traits<char> >::operator<<(double)'
cppcode.o: In function `__static_initialization_and_destruction_0(int, int)':
cppcode.cc:(.text+0x6b): undefined reference to `std::ios_base::Init::Init()'
cppcode.cc:(.text+0x70): undefined reference to `std::ios_base::Init::~Init()'
collect2: ld returned 1 exit status
I assume that this happens because I am using the C compiler. What is the correct way to compile and link this small example?
The idea is that I have the C code running and just invoke the C++ functions, without having to rewrite them in C. Thanks in advance for help!
I am using Ubuntu 12.04, gcc version 4.6.3

You need to link C++ runtime library.
gcc ccode.c cppcode.o -o ccode -lstdc++

You should compile and link separately. Use g++ to link in order to get the proper standard library.
g++ -c cppcode.cc -o cppcode.o
gcc -c ccode.c -o ccode.o
g++ ccode.o cppcode.o -o ccode

The g++ compiler automatically links your program with the standard cpp library.
When you compile with gcc, the linker can find reference to that.
You have two options.
One is to compile the c file with g++. Second is to force the linkage of the standard cpp library.
Here's whats written in gcc guide:
-static-libstdc++
When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.
Run the following command:
gcc ccode.c cppcode.o -o ccode -lstdc++

Related

Hybrid programming of Fortran and C++: Fortran can not call C++ subroutines [duplicate]

This question already has answers here:
Linking Fortran and C++ binaries using gcc
(1 answer)
gfortran undefined references
(1 answer)
Undefined reference to `std::chrono::_V2::system_clock::now()' when linking with gfortran
(1 answer)
Closed 3 years ago.
Recently, I was working on a project where some C++ subroutines are called by Fortran scripts (A Fortran solver intends to have some data-post-processing capability which is from a lib developed in C++). The following procedures replay the error producing process. Here I use quite simple Fortran and C++ scripts for a easy and clear demonstration.
A simple Fortran main program calls a CXX subroutine:
The CXX subroutine - sub1.cxx:
#include <stdio.h>
using namespace :: std;
extern "C" void func_c_();
void func_c_()
{
printf("%d\n", 100);
}
The Fortran main program - sub2.f90:
program func_fortran
implicit none
call func_c()
end program func_fortran
Compile them:
g++ -c sub1.cxx
gfortran -o test sub2.f90 sub1.o
We get the executable - test. Up to now, there is no problem.
Then we replace the sub1.cxx by sub1.1.cxx. It looks like:
#include <iostream>
using namespace :: std;
extern "C" void func_c_();
void func_c_()
{
cout << "I am a CXX." << endl;
}
The Fortran main program is totally the same with the previous one. We did not touch it.
Now we compile the codes:
g++ -c sub1.1.cxx
gfortran -o test sub2.f90 sub1.1.o
We can obtain sub1.1.o. But the error messages are thrown out:
sub1.1.o: In function `func_c_':
sub1.1.cxx:(.text+0xa): undefined reference to `std::cout'
sub1.1.cxx:(.text+0xf): 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*)'
sub1.1.cxx:(.text+0x14): 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> >&)'
sub1.1.cxx:(.text+0x1c): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
sub1.1.o: In function `__static_initialization_and_destruction_0(int, int)':
sub1.1.cxx:(.text+0x46): undefined reference to `std::ios_base::Init::Init()'
sub1.1.cxx:(.text+0x55): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
Compared with sub1.cxx, it seems some C++ standards in sub1.1.cxx e.g. std::cout can not be recognized. Any one could figure this problem out?
Additionally, here I did not use the iso_c_binding from Fortran 2013. I tried this features in some other cases but it does not work either.
You need to link the executable against the c++ standard library:
g++ -c sub1.1.cxx
gfortran -o test sub2.f90 sub1.1.o -lstdc++
With gfortran/g++ you can also use g++ to link against the fortran library:
g++ -c sub1.1.cxx
gfortran -c sub2.f90
g++ -o test sub1.o sub2.o -lgfortran

Codeblocks succeeded in compiling, but gcc failes, Why?

I'm using ubuntu 18.
I'v installed codeblocks ide and bare gnu gcc compiler (command line) both
gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)
code blocks 16.01
I wrote a very simple code to create and print a string variable
Code blocks(with inbuilt gnu gcc compiler) succeeded in compiling. But bare gcc compiler failes
I've tried by including iostream and stdio also
#include <string>
using namespace std;
int main() {
string a = "I am learning C++";
printf("%s",a.c_str());
return 0;
}
codeblocks compiles it successfully and gives the output without raising an error. As well as sololearn online compiler also
I am learning C++
I got into the folder where the cpp file is and gave following command
gcc string_var.cpp -o string_var.out
Bt the bare gcc compiler gives some long stuff of compiler errors which i can't understand
/tmp/ccen8bfp.o: In function `main':
string_var.cpp:(.text+0x20): undefined reference to `std::allocator<char>::allocator()'
string_var.cpp:(.text+0x37): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)'
string_var.cpp:(.text+0x43): undefined reference to `std::allocator<char>::~allocator()'
string_var.cpp:(.text+0x4f): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str() const'
string_var.cpp:(.text+0x74): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
string_var.cpp:(.text+0x96): undefined reference to `std::allocator<char>::~allocator()'
string_var.cpp:(.text+0xb0): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
/tmp/ccen8bfp.o:(.data.rel.local.DW.ref.__gxx_personality_v0[DW.ref.__gxx_personality_v0]+0x0): undefined reference to `__gxx_personality_v0'
collect2: error: ld returned 1 exit status
The GNU Compiler Collection (GCC) can be used to compile many different languages. Some of those languages are common enough that they can use the same front-end program.
C and C++ are two such languages, and both can be compiled with the gcc front-end program. However, the gcc program by default is for C code, and because of that don't use some flags needed to build C++ programs. One such missing thing is that gcc doesn't link with the C++ standard library.
You can solve this by explicitly linking with the library:
gcc string_var.cpp -o string_var.out -lstdc++
Or, even simpler, use the front-end program for C++, g++:
g++ string_var.cpp -o string_var.out
gcc string_var.cpp -o string_var.out
gcc is a C compiler. You want to compile C++ code:
g++ string_var.cpp -o string_var.out
It just so happens that either gcc or g++ works insofar as compiling the actual code, the compiler understand that .cpp files contain C++ code, and proceeds accordingly.
However, when it times to linking the resulting object module, gcc does not provide the runtime C++ library to the linker (it still thinks it's just a C compiler, and has never heard of C++), resulting in your link failure.

Codeblocks C++ Compiling Error on Codeblocks w/ GCC

I have been writing c++ for a little while using Visual Studio on Windows, and I recently switched to Linux Mint, and installed Codeblocks to use as my C++ IDE. I have written a very simple program, which I cannot get to compile:
#include <iostream>
int main()
{
std::cout << "Hello world!" << endl;
std::cin.get();
return 0;
}
I have tried running this, and I get a console error message:
Executing: xterm -T Test -e /usr/bin/cb_console_runner LD_LIBRARY_PATH=$LD_LIBRARY_PATH:. /home/***/workspaces/cpp-workspace/Test/bin/Debug/Test (in /home/***/workspaces/cpp-workspace/Test/.)
Process terminated with status -1 (0 minute(s), 0 second(s))
I have also tried running cc against my main.cpp file, and I get an error message saying:
/tmp/cc4RcEeE.o: In function `main':
main.cpp:(.text+0xe): undefined reference to `std::cout'
main.cpp:(.text+0x13): 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*)'
main.cpp:(.text+0x1d): 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> >&)'
main.cpp:(.text+0x28): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
main.cpp:(.text+0x2f): undefined reference to `std::cin'
main.cpp:(.text+0x34): undefined reference to `std::istream::get()'
/tmp/cc4RcEeE.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0x64): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0x79): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
Additional Information:
I have installed GCC on my machine
I installed Codeblocks using the Mint Software Manager
I have been researching this problem over the course of a week or so, and have been unable to get anything to work. Any help getting this compile would be much appreciated!
EDIT
I have checked through my compiler settings according to the suggestions given, and they all appear correct. I've added a screenshot of my settings in case someone sees something... Also, g++ is not listed as an option in the drop-down for compilers.
My codeblocks settings
cc builds C programs. That won't bring in the standard library for C++, hence the linker errors.
You want a C++ compiler, like the one you have already installed: g++.
Indeed, until you've built your program successfully, you won't be able to execute it.
This ought to be covered in your C++ book, which you can review now.

compiling .cpp with gcc

okay this I did accidentally , compiling .cpp using gcc and not g++
but I actually want to understand the console output, line by line, if it has any sense.
struct a{
int pointer;
int rollno;
};
struct a student,*studentref;
studentref = &student;
studentref->rollno = 141;
studentref->pointer = 8;
cout<<studentref->rollno<<") : "<<studentref->pointer<<endl;
compiling this code with gcc structpointers.cpp -o structp gives the following output:
sourab#sourab:/home/gbear/coding/learningds$ gcc structpointers.cpp -o structp
/tmp/ccXrq1Cv.o: In function `main':
structpointers.cpp:(.text+0x2e): undefined reference to `std::cout'
structpointers.cpp:(.text+0x33): undefined reference to `std::ostream::operator<<(int)'
structpointers.cpp:(.text+0x38): 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> >&)'
structpointers.cpp:(.text+0x40): undefined reference to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
/tmp/ccXrq1Cv.o: In function `__static_initialization_and_destruction_0(int, int)':
structpointers.cpp:(.text+0x6e): undefined reference to `std::ios_base::Init::Init()'
structpointers.cpp:(.text+0x7d): undefined reference to `std::ios_base::Init::~Init()'
collect2: error: ld returned 1 exit status
The most egregious difference between calling g++ and gcc on a .cpp file is that g++ automatically links in the C++ standard library, while gcc does not; all the errors you see are linker errors of missing references to stuff that is provided by the C++ standard library.
(notice that this isn't the only difference; see this question for details)
g++ and gcc are compiler drivers of GNU compiler collection, they have backends which are connected automatically once compilation mode in up.
The errors like "
structpointers.cpp:(.text+0x2e): undefined reference to `std::cout'
are link errors,since you have used gcc to compile cpp,the standard libraries specifically for cpp are not present, so it could not find syntax like std::cout etc.
you can also refer to : compiling with g++

To Create a DLL for C++ program in CYGWIN

I am trying to convert an Math.cpp into a dll in Cygwin.
I am trying this code in Cygwin to compile.
gcc -c Math.cpp
Now am trying to convert the .o in into .dll. For this I used the below code
gcc -shared -o Math.dll Math.o
where am getting a huge error message in cygwin which says "Math.o:Math.cpp:(.text+0x55): undefined reference to std::ios_base::Init::Init()'
Math.o:Math.cpp:(.text+0x55): relocation truncated to fit: R_X86_64_PC32 against undefined symbolstd::ios_base::Init::Init()Math.o:Math.cpp:(.text$_ZN11Mathematics5inputEv[_ZN11Mathematics5inputEv]+0x21): undefined reference to `std::basic_ostream >& std::operator<< >(std::basic_ostream >&, char const*)''",etc.
In my C++ program namespace is std;
class name is Mathematics, there are two methods input() and add() and there is a main method which calls these methods.
Use g++ rather than gcc
This will cause gcc to link with the standard C++ libary, which should resolve those symbols.