Reputation: 4273
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 to
graph_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 ?
Upvotes: 1
Views: 6438
Reputation: 409442
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
Upvotes: 3