3

I would like to write a c++ wrapper for a C API. for this it is most convenient to just include the C-API header in my own header, but this also includes the header into the file of the outer system, that should not be exposed to the C-API.

capi.h

enum MyFlags {
    MY_FLAG_A,
    MY_FLAG_B,
};

void FOO_bar(int flags);

cppapi.hh

#include "capi.h"

enum class MyFlags { 
    A = MY_FLAG_A, 
    B = MY_FLAG_B 
};

namespace foo {
    void bar(MyFlags flags) { 
        FOO_bar((int)flags); 
    }
}

it is just to translate c naming convention into c++ language features. So when using the C++ variant of the language, I would like that the c_api is not available to my auto completion and therefore not accidently used.

jww
  • 97,681
  • 90
  • 411
  • 885
Arne
  • 7,921
  • 9
  • 48
  • 66

2 Answers2

6

Define a namespace detail in your projects namespace, and include the C header there.

If the C header does not define en extern "C"- block when included from C++, do one of these:

  • Wrap with an external extern "C" block and verify the C header is, if included thus, valid and equivalent C++. (Special attention to enum sizes and inline functions).
  • Make it valid and equivalent C++ using #ifdef __cplusplus.

Thus, all those C functions are hidden in the internal implementation-detail namespace, and won't bother anyone.

namespace foo {
    namespace internal {
        extern "C" {
            #include "capi.h"
        }
    }
    // Function alias
    using bar = internal::FOO_bar;
    // Type alias
    using config_t = internal::FOO_config;
}

Selectively get those symbols you need into the FOO-namespace using using.

BTW: Your forwarder-function should really be inline!

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • Is it guaranteed that the linker won't choke on this? – Axel Jul 31 '14 at 15:02
  • 1
    The linker won't choke, the compiler might if the header uses C++ keywords like normal identifiers. – Deduplicator Jul 31 '14 at 15:03
  • Ok. There's even an explanation in the answer to http://stackoverflow.com/questions/9685994/c-extern-c-functions-inside-a-namespace: The namespace information of the symbols defined `extern "C"` won't be visible to the linker, so this should work. – Axel Jul 31 '14 at 15:12
  • Also, use `using` for getting those names you want into your module namespace. – Deduplicator Jul 31 '14 at 15:17
-1

You should be able to arrange things using

#ifdef __cplusplus
/* C++ code here, including #include*/
#else
/*C code*/
#endif
Bathsheba
  • 231,907
  • 34
  • 361
  • 483