1

I have a header file

// Creates a new graph with n vertices and no edges
graph_t *graph_create(int n);

A .c file

graph_t *graph_create(int n)
{
    graph_t *g;
    int     i;

    //g = malloc(sizeof(graph_t));
    g->V = n;
    g->E = 0; 

    return g;
}

This is how my CMakeLists.txt looks like

cmake_minimum_required(VERSION 3.3)
project(Thesis)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES main.cpp graph.h graph.c shared.h)
add_executable(Thesis ${SOURCE_FILES})

I call graph_t *g = graph_create(15); from main.cpp and I get the following error saying that the method is undefined:

"C:\Program Files (x86)\JetBrains\CLion 1.2.4\bin\cmake\bin\cmake.exe" --build C:\Users\Shiro.CLion12\system\cmake\generated\6e6ca233\6e6ca233\Debug --target Thesis -- -j 8 Scanning dependencies of target Thesis [ 66%] Building CXX object CMakeFiles/Thesis.dir/main.cpp.obj [ 66%] Building C object CMakeFiles/Thesis.dir/graph.c.obj [100%] Linking CXX executable Thesis.exe CMakeFiles\Thesis.dir/objects.a(main.cpp.obj): In function main': C:/Users/Shiro/ClionProjects/Thesis/main.cpp:7: undefined reference tograph_create(int)' collect2.exe: error: ld returned 1 exit status CMakeFiles\Thesis.dir\build.make:121: recipe for target 'Thesis.exe' failed mingw32-make.exe[3]: [Thesis.exe] Error 1 CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/Thesis.dir/all' failed CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/Thesis.dir/rule' failed Makefile:117: recipe for target 'Thesis' failed mingw32-make.exe[2]: [CMakeFiles/Thesis.dir/all] Error 2 mingw32-make.exe[1]: [CMakeFiles/Thesis.dir/rule] Error 2 mingw32-make.exe: [Thesis] Error 2

What am I doing wrong ?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
dimitris93
  • 4,155
  • 11
  • 50
  • 86

1 Answers1

3

Assuming the function is defined in the graph.c C source file, the problem is because of name mangling.

C++ uses mangled names to be able to handle things like overloading, and this is not needed for C. When you want to use a function from a C source file or C library, you need to tell the C++ compiler to not use mangled names, and this is done with the extern "C" construct, as in

extern "C" graph_t *graph_create(int n);

There's a problem with that though, and that is that the C compiler will not know what you mean by extern "C", and it will complain. For this you need to use conditional compilation using the preprocessor, and check if the header file is being used by the C++ or the C compiler. This is done by checking for the existence of the __cplusplus macro:

#ifdef __cplusplus
extern "C"
#endif
graph_t *graph_create(int n);

If you have multiple functions, then put them in a brace-enclose block:

#ifdef __cplusplus
extern "C" {
#endif

graph_t *graph_create(int n);
// More functions here...

#ifdef __cplusplus
}  // End of extern "C" block
#endif
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Hmm, I was expecting an answer in the lines of, you need to chance X settings. But this definitely worked. So, I actually have to add `#ifdef __cplusplus extern "C" #endif` on every header file ? Will this create any problems with compatibility of any sort ? I mean is this a clean solution that people use ? I understand that this is a "problem" with C and C++ compilers being different, not the actual IDE, so this solution is used in all programs that are using C and C++ at the same time ? – dimitris93 Feb 22 '16 at 13:54
  • 1
    @Shiro If you look at just about any C library you find on the world wide Internet, you will see this. It's the only way to go around the name-mangling problem. And it's completely safe and will only impact compilation time marginally (as in not measurable). – Some programmer dude Feb 22 '16 at 13:58
  • Well that's great news, and thanks for the amazing explanation in your answer about mangled names – dimitris93 Feb 22 '16 at 14:00
  • Should I put the whole header file in those brackets ? or just the functions ? is there a real difference ? – dimitris93 Feb 22 '16 at 14:04
  • 1
    @Shiro It doesn't matter, only functions and their prototypes will be affected. I've seen both styles. – Some programmer dude Feb 22 '16 at 14:42