0

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

natascha
  • 151
  • 1
  • 7
  • You have a c++ dependency; you should use `gcc` to build `ccode.o`, but then use `g++` to link the .o files together. – Joe Mar 13 '13 at 17:49
  • Don't include headers, even standard ones, inside other headers. Not unless they explicitly define type/constants which are needed *in your header*. – StoryTeller - Unslander Monica Mar 13 '13 at 17:51
  • @StoryTeller: thanks for the hint, I will fix this – natascha Mar 13 '13 at 18:05
  • @Joe: thanks for your answer, I guess this is equivalent to using gcc in combination with -lstdc++? Or is one way better than the other? – natascha Mar 13 '13 at 18:05
  • There are some other differences: http://stackoverflow.com/questions/6735277/any-difference-in-linking-with-gcc-vs-g – Joe Mar 13 '13 at 18:54

3 Answers3

2

You need to link C++ runtime library.

gcc ccode.c cppcode.o -o ccode -lstdc++
Valeri Atamaniouk
  • 5,125
  • 2
  • 16
  • 18
1

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
nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • Thanks @nneonneo for your answer. This is working now since I have a main function in the ccode.c. How would it need to be compiled if there is no main and I just need to invoke the functions (from another program, in particular from my Lua code)? I managed to build both codes (.cc and .c) separately, but I am currently not able to link them correctly. – natascha Mar 14 '13 at 12:48
  • You would build a *shared library* and load the library from your Lua code somehow. – nneonneo Mar 14 '13 at 16:12
0

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++
stdcall
  • 27,613
  • 18
  • 81
  • 125