upb - a small, low-level protocol buffer library For API documentation, see the header files. To build (the core library is ANSI C99 and has no dependencies): $ make Other useful targets: $ make test $ make benchmark $ make lua (requires lua libraries to be installed) The tests and benchmarks have the following dependencies (Ubuntu package names in parentheses): - Google's protobuf compiler + libraries (protobuf-compiler, libprotobuf-dev) - Lua binary and libraries (lua5.1, liblua5.1-dev) Issue tracking is on Google Code: http://code.google.com/p/upb/issues/list A manual is forthcoming, for now see wiki docs at: https://github.com/haberman/upb/wiki API and ABI are both subject to change! Please do not distribute as a shared library for this reason (for now at least). TODO ==== The issue tracker contains small-to-medium tasks that need doing; but here are the major things that are broken or not yet implemented yet: - serialization isn't written yet (only deserialization) C/C++ API ========= upb's main interfaces are defined in .h files (like upb/def.h). These header files are coded in such a way that they are not only compatible with C and C++ but provide idiomatic interfaces to both (functions for C, classes for C++). Here is the general strategy/pattern for this. I'll explain it piece by piece. // This defines a type called upb::Foo in C++ or upb_foo in C. In both cases // there is a typedef for upb_foo, which is important since this is how the // C functions are defined (which are exposed to both C and C++). #ifdef __cplusplus namespace upb { class Foo; } typedef upb::Foo upb_foo; extern "C" { #else struct upb_foo; typedef struct upb_foo upb_foo; #endif // Here is the actual definition of the class/struct. In C++ we get a class // called upb::Foo and in C we get a struct called "struct upb_foo", but both // have the same members and the C++ version is "standard-layout" according // to C++11. This means that the two should be compatible. // // In addition to being completely accessible from C, it also provides C++ // niceities like methods (instead of bare functions). We also get // encapsulation in C++, even though this is impossible to provide in C. We // provide all method documentation in the C++ class, since the class/method // syntax is nicer to read than the bare functions of C. #ifdef __cplusplus class upb::Foo { public: // Method documentation for DoBar(). void DoBar(int32_t x); // Method documentation for IsSpicy(). bool IsSpicy(); private: #else struct upb_foo { #endif int32_t private_member; }; // Next follows the C API, which is how the functionality is actually // implemented. We omit documentation here because everything was documented // in the C++ class, and it's easy to match the functions 1:1 to the C++ // methods. void upb_foo_dobar(upb_foo *f, int32_t x); bool upb_foo_isspicy(upb_foo *f); // Finally we include inline definitions of the C++ methods, which are nothing // but this wrappers around the C functions. Since these are inline, the C++ // API imposes no overhead. #ifdef __cplusplus } // extern "C" namespace upb { inline void Foo::DoBar(int32_t x) { upb_foo_dobar(this, x); } inline bool Foo::IsSpicy() { return upb_foo_isspicy(this); } } #endif This scheme works pretty nicely. It adds a bit of noise to the header file, but gives nice, zero-overhead APIs to both C and C++ without having to duplicate the API documentation. The biggest bummer is that there isn't any good way to use C++ inheritance even for types which are trying to express inheritance in C. C++ just doesn't give any guarantees about how it will arrange data members in base classes, so we can't use C++ inheritance while interoperating with C layouts. The biggest effect of this is that we can't get C++'s nice implicit upcasts; all upcasts have to be explicit, which is a pain. CONTACT ======= Author: Josh Haberman (jhaberman@gmail.com, haberman@google.com) See LICENSE for copyright information.