Question

When preparing a library (let's call it libfoo), I find myself presented with the following dilemma: do I write it as a C++ library with a C wrapper:

namespace Foo {
  class Bar {
    ...
  };
}

/* Separate C header. #ifdef __cplusplus omitted for brevity. */
extern "C" {
  typedef void *FooBar;
  FooBar* foo_bar_new() { return new Foo::Bar; }
  void foo_bar_delete(FooBar *bar) { delete bar; }
}

Or is it better to write it as a C library with a C++ wrapper:

/* foo/bar.h. Again, #ifdef __cplusplus stuff omitted. */

typedef struct {
  /* ... */
} FooBar;

void foo_bar_init(FooBar *self) { /* ... */ }
void foo_bar_deinit(FooBar *self) { /* ... */ }

/* foo/bar.hpp */

namespace Foo {
  class Bar {
    /* ... */
    FooBar self;
  }

  Bar::Bar() {
    foo_bar_init(&self);
  }

  Bar::~Bar() {
    foo_bar_deinit(&self);
  }
}

Which do you prefer, and why? I favour the latter because it means I don't have to worry about my C functions accidentally having exceptions bubble up, plus I prefer C as a language as I feel that it's a smaller semantic minefield. What do other people think?

EDIT: So many good answers. Thanks all. It's a shame that I can only accept one.

Was it helpful?

Solution

Small points:

When you write C library it is useful anywhere - in C, in C++ (with wrapper) and many other languages like Python, Java using bindings etc and most important it requires only C runtime.

When you write C++ wrapper you also need to write a C wrapper, but it is not as simple as you think, for example:

c_api.h:

extern "C" {
  typedef void *Foo;
  Foo create_foo();
}

c_api.cpp:

void *create_foo() 
{
    return new foo::Foo();
}

What is wrong? it may throw! and the program will crash as C does not have stack unwinding semantics. So you need something like:

void *create_foo() 
{
    try {
       return new foo::Foo();
    }
    catch(...) { return 0; }
}

And this for every C++ api function.

So I think that writing a C library and providing a separate C++ wrapper is better solution.

Also it would not require linking with C++ runtime library.

OTHER TIPS

Write the library in the language you prefer to write libraries in. It doesn't technically much matter which way you wrap. Although some C projects may aim to exclude libraries that aren't C whereas it'd be odd for a C++ project to exclude libraries written in C, that's mostly a philosophical objection than a practical one.

Wrapping C in a C++ wrapper will likely result in a slightly larger wrapper but be more acceptable to C programmers.

Note that if you are distributing binaries, C's simplicity is advantageous.

If you prefer to write in C, why do you need C++ wrapper? C++ client can use C-style API interface. On the other hand, you you prefer C++, it is necessary to have C wrapper for C clients.

If your lib will ever have to be distributed as a binary + header (instead of shipping the source code), you will find that a C API is more universally linkable, since C usually is the smallest common API on any platform.

This is why I usually had to make C APIs with inline C++ wrappers around them for the projects I did in the last decade that needed an API. Since the programs were all in C++, this meant I had to make a C wrapper API around C++ code, just to put another wrapping C++ API around it.

Assuming compilation without link-time optimizations, a C compiler can't inline the wrapper functions as it doesn't know how to handle C++ calls - but a C++ compiler can easily inline C calls.

Therefore, it might be a good idea to create a C++ wrapper for the C library, instead of the other way around.

I personally prefer to use C++ and would wrap it to C. But infact it's a matter of taste and you'd have to make your own decision how you'd like it. If you feel more comfortable writing the library in C then go for it and wrap it for C++.

About the exceptions: You can catch them in every function wrapped for C and return an error code for them, by e.g. having an own exception class which has already a numeric error code value which you may return to your C functions, others which might have been thrown by any other libraries can be translated to something else, however you should have caught them earlier anyway.

If you feel comfortable with writing your library in C then do it. It will be more portable as a C library and has no issues with exceptions as you mentioned. It is uncommon to start with a C++ library and wrap it in C.

It also depends a lot on what you plan to use in your library. If it in turn could benefit greatly from other C++ libraries, then use C++.

It could also be argued, that if your library is going to be very big (internally, not necessarily API wise) it can be easier to implement it in C++. (It is not my cup of tea, I prefer C, but some people swear by C++.)

Also keep in mind, that C++ uses a runtime that pretty much demands an operating system, for exception support.

If you envision your library to be used as a foundation for an operating system, or to be used in environments without an operating system you either have to know how to disable exception support, avoiding a lot (all?) of STL and provide your own allocator and deallocator. It's not impossible, but you need to know exactly what you do.

C is more suited to those low level kinds of things.

Personally I prefer to write it in C++, then expose the C interface using a wrapper. Mostly because I'd rather write in a proper OO language. I'd use an OO style C wrapper too, liek I outline in this post I wrote a pretty detailed explanation about what you need to d to call OO C++ from C in this post Developing C wrapper API for Object-Oriented C++ code

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top