Search code examples
c++cmakelinkerexterncalling-convention

Calling C code from C++ in a CMake project. Undefined symbol. Have extern C


I'm trying to build a CMake project that calls C code from C++, and I'm getting undefined symbols, even though I'm (AFAIK) properly using "extern C".

CMakeLists.txt:

cmake_minimum_required(VERSION 3.0)
project(CTest LANGUAGES CXX)
add_executable(test main.cpp lib.c)

main.cpp:

#include "lib.h"

int main()
{
    printit();
    return 0;
}

lib.c:

#include <stdio.h>
#include "lib.h"

int printit()
{
    printf("Hello world\n");
    return 0;
}

lib.h:

extern "C" int printit();

That gives me an "undefined reference to printit" error.

If I simply build this from the command-line, it works fine:

g++ main.cpp lib.c

What am I doing wrong?


Solution

  • extern "C" is C++ syntax. Your header lib.h therefore cannot be used from C. If you change it as follows it can be used from C++ and C as well.

    #ifndef LIB_H_HEADER
    #define LIB_H_HEADER
    
    #ifdef __cplusplus
    extern "C" 
    {
    #endif
    
    int printit();
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* LIB_H_HEADER */
    

    As you have both C and CXX sources your project call should enable C as well project(CTest LANGUAGES C CXX) in your CMakeLists.txt.