Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a library with C and C++ interfaces, which way to wrap?

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.

like image 498
Jack Kelly Avatar asked Oct 12 '10 07:10

Jack Kelly


People also ask

Are C libraries written in C?

In a typical case, the C standard library is written primarily in C, and the C++ standard library primarily in C++. To give some concrete numbers, Microsoft's standard library has ~1050 C and C++ files, and 37 assembly language files.

Should I write my library in C or C++?

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. Save this answer.

How do I combine C and C++?

Even if your program is primarily C code but makes use of C++ libraries, you need to link C++ runtime support libraries provided with the C++ compiler into your program. The easiest and best way to do that is to use CC , the C++ compiler driver, to do the linking.

Can you use libraries in C?

Functions in a C library can be used and accessed by programmers to create several different programs. As a programmer, you may find yourself using the same function or functions repeatedly. In this case, it is best to put this function or functions in a library to speed up the compilation of the program.


2 Answers

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.

like image 100
Artyom Avatar answered Nov 13 '22 03:11

Artyom


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.

like image 37
Eamon Nerbonne Avatar answered Nov 13 '22 04:11

Eamon Nerbonne