jdi jdi - 2 months ago 6x
C Question

Wrap C++ namespaced enum to C interface

I'm trying to wrap an existing 3rd party C++ library to a C interface, so that it can be used in bindings for another language. I'm having trouble figuring out how to wrap a namespaced enum, as opposed to just redefining it:

// Existing C++ 3rd party library header
namespace foo {
enum Fruit {
APPLE = 0,

So then I have my wrapped.{h,cpp} with an
extern "C"
block, and I just can't figure out how to export the
enum into the C interface

// wrapped.h
#ifdef __cplusplus
extern "C" {

// I don't want to do this
typedef enum Fruit {
APPLE = 0,
} Fruit;

#ifdef __cplusplus

Is it possible to export (mirror)
from the C++ library into my C wrapper as


edit: I just noticed that you wanted to wrap an existing library without modifying it.

I fear you are about out of luck then. In general there is just no way of extracting just the enum members out of C++ code without the C compiler choking.

In practice you've got the choice whether to programmatically translate your own set of enumerations into the C++ versions in the interface, try to mirror the C++ exactly and place a bunch of static assertions to double-check, or in theory even filtering them out through scripts.

There are simply no good options here I'm afraid. For the record I would tend to prefer the first of these bad options.

Personally I probably would be lazy and just stick to the C version.

Still, if required and the number of constants is large you can do a bit of macro magic to get a single definition with C-style "namespaces" as required.

First a single header defining all enum entries through a macro:

/* Fruit.h */

Then in the C header:

/* C interface */
typedef enum {
#   define FOO_ENUM(id) FOO_##id
#   include "Fruit.h"
#   undef FOO_ENUM
} Foo_Fruit_t;

And finally in the C++ header:

// C++ interface
namespace Foo {
    enum Fruit_t {
#       define FOO_ENUM(id) id
#       include "Fruit.h"
#       undef FOO_ENUM

There are many alternatives of course. For instance if you don't mind polluting the global namespace in C++ then can always define the full enumeration directly in the C interface and copy the individual enum members in the C++ version of the definition.