Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

C++ is quite portable on its own. But wrapping in C can be useful indeed, for example to enable using that library with other language, like Rust which can bind with C, but not with C++. But what is the point of writing something in C++, wrapping that in C and then wrapping it back in C++? Can't the first level be used directly from C++?


I'm not sure if this is the author's reason, but one reason is that the C++ wrapper could be implemented entirely in a header file, giving you ABI compatibility that you might not have otherwise.


My guess would be that the C wrapper looks different then the underlying C++. Or more, the C++ exposes a different set of functions and isn't stable, where the C wrapper is stable. By wrapping the C wrapper, you can also give the C++ wrapper API stability since it only depends on the C API. That of course depends on what all the C wrapper actually does, and whether a subset of your internal C++ can be declared 'stable' for your API (And if you want to do that).


You can use the C wrappers in C++ code, of course, but it's often not very convenient. For example you normally have to call destructors of the objects created by the library with explicit calls to some C functions from the C wrappers API. By adding another layer of the C++ wrappers over the C wrappers you retain the ABI stability without the awkwardness of C style code in your C++ client code.


I find this is the first thing a lot of C++ devs do if the wrappers don't exist. It is actually kind of important in C++ if your app uses exceptions and you want to have exception (somewhat-)safe code. Using the C API directly would require a lot of boilerplate to ensure all allocated things are cleaned up if an exception is thrown.


I don't really understand why you can't expose a stable ABI right from the first C++ layer. It shouldn't be any harder than making such ABI in the third layer, and will avoid many extra function calls which don't come for free.


It's enough to add a member to a class to break its ABI compatibility. It's possible to expose a stable C++ API but that normally requires extra classes implementing the PIMPL idiom, so basically the 3rd, C++ layer described in the article. PIMPL doesn't require the C API (2nd layer), of course, but if you need the C API anyway, for calling your lib from scripting languages, for example, then the 3 layers make sense. Lots of tedious work, but that's C++...


What I mean is, instead of making [Core C++ library] -> [stable C interface] -> [stable C++ interface] one could make both directly:

[Core C++ library] -> [stable C interface]

[Core C++ library] -> [stable C++ interface]

That would avoid extra overheard in the last case.


As far as the number of layers is concerned it's the same. The advantage of writing the C++ stable API on top of C API is that both C and (stable) C++ API have the same functionality/semantics - if you write those two separately on top of the primary C++ API they can easily diverge.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: