The full video from CppCon is available here: https://www.youtube.com/watch?v=PVYdHDm0q6Y
C++ provides a much richer set of abstractions than C. Classes, templates, overloading, and other core C++ features can be leveraged for more readable syntax, better compile time typechecking, more open ended genericity and improved modularity. On the flip side, C89 still boasts some advantages over C++, especially when viewed through a pragmatic lens. C ABIs on many platforms have been stable for decades, practically every language supports binding to C code through foreign function interfaces, and including nearly any C89 header has a negligible effect on compile time on modern computers.
The hourglass pattern provides the best of both worlds. By placing a headers-only C++ interface on top of a minimal C89 interface, it makes ABI issues a non-concern, and enables just a single binary to be shipped for a given platform. It makes providing bindings from other languages easier, and prevents ABI issues like incompatibilities between debug and release variants of runtimes.
This talk provides an overview of the pattern and teaches practical techniques for its implementation using C++14. Real shipping projects inspired the best practices described in the slides.
Code corresponding to this presentation can be found here: https://github.com/CppCon/CppCon2014/tree/master/Presentations/Hourglass%20Interfaces%20for%20C%2B%2B%20APIs%20-%20Stefanus%20Du%20Toit%20-%20CppCon%202014/code
9. My Goal for Libraries
Get out of the client’s way.
10. My Goal for Libraries
Don’t make my clients:
• build my code if they don’t want to
• change how they build their code
• rebuild their code because I shipped a fix in mine
• learn a new language if they don’t want to
11.
12.
13. Why does this help?
• Avoids ABI-related binary compatibility issues
• Enforces no use of non-trivial C++ types in the
binary interface (e.g. std::string)
• Keeps internal layout of data types a secret
• Makes binding to other languages much easier
!
• Still get all the convenience of C++ at both ends
14. Example: libhairpoll
• A library for creating hair-related polls, taking
votes, and tallying the results
18. Parts of C to use in the thin API
• C89 + const and // comments
• Functions, but no variadic functions
• C primitive types (char, void, etc.)
• Pointers
• forward-declared structs
• enumerations
• Function pointers are OK, too
37. Symbol visibility
On Clang and GCC, add to your compile:
!
-fvisibility=hidden
!
(applies to library only)
38. Remember to extern “C”!
#ifdef __cplusplus
extern "C" {
#endif
!
// C API goes here
!
#ifdef __cplusplus
} // extern "C"
#endif
39. Lifetime and Ownership
• Keep it simple: construct (if needed) and destruct
• Always use RAII on the client side!
• Can use refcounting (e.g. shared_ptr) both
internally to the library and in the client
• For callbacks, you can use the stack
41. Foreign Function Interfaces
• “something that allows calling code written in one
language from another language”
• C = de-facto standard
• Languages with support for calling C functions in
shared libraries include:
• Common Lisp, Java, JavaScript, Matlab, .NET
(C#, F#, etc.), Python, Ruby, OCaml, basically everything…
44. Summary
• Hourglass = C++ on top of C89 on top of C++
• Avoids ABI issues, sneaky dependencies, etc.
• Hides object layout and other implementation
details
• Makes FFI bindings easy