Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
}
like image 507
rajeshk Avatar asked Apr 17 '13 11:04

rajeshk


People also ask

Why should we avoid use of using namespace in header files?

cpp file (at file scope), or inside a class or function definition. In general, avoid putting using directives in header files (*. h) because any file that includes that header will bring everything in the namespace into scope, which can cause name hiding and name collision problems that are very difficult to debug.

Should you use namespace in header file?

Under no circumstances must you use namespace std within a header file, that's a recipe for errors straight away.

Should C file include header?

In C program should necessarily contain the header file which stands for standard input and output used to take input with the help of scanf() and printf() function respectively.

Can I use using namespace std in header file?

Since you can't put a namespace using statement at the top level of the header file, you must use a fully qualified name for Standard Library classes or objects in the header file. Thus, expect to see and write lots of std::string, std::cout, std::ostream, etc. in header files.


1 Answers

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.

like image 159
Arne Mertz Avatar answered Oct 13 '22 01:10

Arne Mertz