1
votes

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 ?

1
@Niall Thanks, this also helpeddimitris93

1 Answers

3
votes

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