Including C++ header file with namespace in C source file causes compilation error

25,704

You cannot use namespaces in C, extern "C" also is not allowed in C. So what could be a solution: Your C++ module defines a set of functions in namespace SystemThreadUtils that need to get called in C-Code. Since you cannot do that directly, you will have to write a C-conformant wrapper around them:

//C/C++ - header "sys_unicode_for_c.h"

#ifdef __cplusplus
extern "C" {
#endif

  void STU_funcInit();
  void STU_funcTerm();

#ifdef __cplusplus
} //end extern "C"
#endif

//C++-source: sys_unicode_for_c.hpp
#include "sys_unicode.h"

extern "C" {
  void STU_funcInit() {
    SystemThreadUtils::funcInit();
  }
  void STU_funcTerm() {
    SystemThreadUtils::funcTerm();
  }
}

Meaning: you need a header that is valid C code and declares a delegating function for each C++ function you need to call from C. The source is in C++ and just does the call.

See Calling C++ functions from C file as well.

Share:
25,704
rajeshk
Author by

rajeshk

I'm an embedded freelance software programmer, primarily programming in C, C++ Linux. I also do HTML and JavaScript sometimes. Lives and works in London.

Updated on June 11, 2020

Comments

  • rajeshk
    rajeshk almost 4 years

    I'm not an expert C++ programmer, and i have been recently doing a trick thing in C++ which is causing me the below issue.

    Objective of my task: Specific non system thread (cooperative threading actually) safe module is duplicated to create a system thread safe version to support different needs in the system. But instead of creating sys_XXX functions to keep the compatibility, we have decided to create a namespace to protect the system thread version in a C++ header file. I can actually include this in the CPP file and work happily but i just realised my funcInit call is not called before it reaches the CPP file control. Unfortunately this init for the cooperative threading version is in a C file. Now i need to init my system thread safe version from the same place, but im have been blocked by the compilation error which are hard to solve from my knowledge.

    Compilation Error log:-

    In file included from sysinit.c:87:
    sys_unicode.h:39: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'SystemThreadUtils' <== corresponds to line [namespace SystemThreadUtils {]
    sysinit.c:88:
    sysinit.c:512: error: expected identifier or '(' before string constant <== corresponds to line [extern "C" bool SystemThreadUtils::funcInit(void);]
    sysinit.c:513: error: expected identifier or '(' before string constant <== corresponds to line [extern "C" bool SystemThreadUtils::funcTerm(void);]
    sysinit.c: In function 'SysInit':
    sysinit.c:817: error: 'SystemThreadUtils' undeclared (first use in this function) <= corresponds to line [SystemThreadUtils::funcInit();]
    sysinit.c:817: error: (Each undeclared identifier is reported only once
    sysinit.c:817: error: for each function it appears in.)
    sysinit.c:817: error: expected ')' before ':' token
    sysinit.c: In function 'SysTerm':
    sysinit.c:2737: error: expected expression before ':' token <== corresponds to line [SystemThreadUtils::funcTerm();]
    sysinit.c:2737: warning: label 'SystemThreadUtils' defined but not used
    

    Source and header snippets FYI :-

    C header file (unicode.h):

    // all functions called from the C source file
    funcInit();
    funcA();
    funcB();
    funcTerm();
    

    C header file (unicode.c):

    // all functions called from the C source file
    funcInit() {
    }
    funcA() {
    }
    funcB() {
    }
    funcTerm() {
    }
    

    C++ header file (sys_unicode.h):

    #include "unicode.h"
    namespace SystemThreadUtils {
    
        // below functions called from the C source file
        extern "C" funcInit();
        extern "C" funcTerm();
    
        // below functions called from the CPP source file
        funcA();
        funcB();
    }
    

    C++ source definition (sys_unicode.cpp):

    #include "sys_unicode.h"
    
    namespace SystemThreadUtils {
    
        // below functions are called from C source
        funcInit() {
        }
        funcTerm() {
        }
    
        // below methods are called from CPP source
        funcA() {
        }
        funcB() {
        }
    }
    

    CPP source # 1 (utils.cpp):

    #include "sys_unicode.h"
    
    using namespace SystemThreadUtils;
    
    utils::utils_init()
    {
       funcA();
       funcB();
    }
    

    C source #2 (sysinit.c):

    #include "sys_unicode.h"
    
    extern "C" bool SystemThreadUtils::funcInit(void);
    extern "C" bool SystemThreadUtils::funcTerm(void);
    
    SysInit ()
    {
       funcInit(); // non system thread safe version
       SystemThreadUtils::funcInit();  // system thread safe version
    }
    SysTerm ()
    {
       funcTerm(); // non system thread safe version
       SystemThreadUtils::funcTerm();  // system thread safe version
    }