|
|
|
@ -1,53 +1,132 @@ |
|
|
|
|
|
|
|
|
|
# μpb - a small protobuf implementation in C |
|
|
|
|
|
|
|
|
|
[](https://travis-ci.org/google/upb) |
|
|
|
|
[](https://coveralls.io/r/google/upb?branch=master) |
|
|
|
|
|
|
|
|
|
μpb is a small protobuf implementation written in C. |
|
|
|
|
|Platform|Build Status| |
|
|
|
|
|--------|------------| |
|
|
|
|
|macOS|[](https://fusion.corp.google.com/projectanalysis/summary/KOKORO/prod%3Aupb%2Fmacos%2Fcontinuous)| |
|
|
|
|
|ubuntu|[](https://fusion.corp.google.com/projectanalysis/summary/KOKORO/prod%3Aupb%2Fubuntu%2Fcontinuous)| |
|
|
|
|
|
|
|
|
|
μpb (often written 'upb') is a small protobuf implementation written in C. |
|
|
|
|
|
|
|
|
|
upb generates a C API for creating, parsing, and serializing messages |
|
|
|
|
as declared in `.proto` files. upb is heavily arena-based -- all |
|
|
|
|
messages always live in an arena. You control where the arena gets |
|
|
|
|
memory from, so the arena can come from stack memory, for example. |
|
|
|
|
Here is a simple example (`ConformanceRequest` and `ConformanceResponse` |
|
|
|
|
are generated message types): |
|
|
|
|
|
|
|
|
|
```c |
|
|
|
|
#include "conformance/conformance.upb.h" |
|
|
|
|
|
|
|
|
|
void foo(const char* data, size_t size) { |
|
|
|
|
upb_arena *arena; |
|
|
|
|
conformance_ConformanceRequest *request; |
|
|
|
|
conformance_ConformanceResponse *response; |
|
|
|
|
|
|
|
|
|
arena = upb_arena_new(); |
|
|
|
|
request = conformance_ConformanceRequest_parse(data, size, arena); |
|
|
|
|
response = conformance_ConformanceResponse_new(arena); |
|
|
|
|
|
|
|
|
|
switch (conformance_ConformanceRequest_payload_case(request)) { |
|
|
|
|
case conformance_ConformanceRequest_payload_protobuf_payload: { |
|
|
|
|
upb_strview payload = conformance_ConformanceRequest_protobuf_payload(request); |
|
|
|
|
// ... |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case conformance_ConformanceRequest_payload_NOT_SET: |
|
|
|
|
fprintf(stderr, "conformance_upb: Request didn't have payload.\n"); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: { |
|
|
|
|
static const char msg[] = "Unsupported input format."; |
|
|
|
|
conformance_ConformanceResponse_set_skipped( |
|
|
|
|
response, upb_strview_make(msg, sizeof(msg))); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
upb_arena_free(arena); |
|
|
|
|
} |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
Messages are opaque, so you always have to use generated getter/setter |
|
|
|
|
methods to read/write fields. This is somewhat unfortunate for C |
|
|
|
|
because the function names are long, but this is necessary to provide |
|
|
|
|
correct semantics for oneof fields, proto2 presence, etc. It is also |
|
|
|
|
necessary for providing a stable ABI, in cases where that is desired. |
|
|
|
|
|
|
|
|
|
API and ABI are both subject to change! Please do not distribute |
|
|
|
|
as a shared library for this reason (for now at least). |
|
|
|
|
|
|
|
|
|
## Building the core libraries |
|
|
|
|
## Using upb in your project |
|
|
|
|
|
|
|
|
|
The core libraries are pure C99 and have no dependencies. |
|
|
|
|
Currently only Bazel is supported (CMake support is partial and incomplete |
|
|
|
|
but full CMake support is an eventual goal). |
|
|
|
|
|
|
|
|
|
$ make |
|
|
|
|
To use upb in your Bazel project, first add upb to your `WORKSPACE` file, |
|
|
|
|
either as a `git_repository()` or as a `new_local_repository()` with a |
|
|
|
|
Git Submodule: |
|
|
|
|
|
|
|
|
|
This will create a separate C library for each core library |
|
|
|
|
in `lib/`. They are built separately to help your binaries |
|
|
|
|
slim, so you don't need to link in things you neither want |
|
|
|
|
or need. |
|
|
|
|
```python |
|
|
|
|
# Add this to your WORKSPACE file. |
|
|
|
|
git_repository( |
|
|
|
|
name = "upb", |
|
|
|
|
remote = "https://github.com/protocolbuffers/upb.git", |
|
|
|
|
# You may want to substitute a more recent commit here. |
|
|
|
|
commit = "d5af87d06bbe3abad66970ce9c7ae0a7de8bb3c6", |
|
|
|
|
) |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
Other useful targets: |
|
|
|
|
Then in your BUILD file you can add `upb_proto_library()` rules that |
|
|
|
|
generate code for a corresponding `proto_library()` rule. For |
|
|
|
|
example: |
|
|
|
|
|
|
|
|
|
$ make tests |
|
|
|
|
$ make test |
|
|
|
|
```python |
|
|
|
|
# Add this to your BUILD file. |
|
|
|
|
load(":upb_proto_library.bzl", "upb_proto_library") |
|
|
|
|
|
|
|
|
|
## C and C++ API |
|
|
|
|
proto_library( |
|
|
|
|
name = "foo_proto", |
|
|
|
|
srcs = ["foo.proto"], |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
The public C/C++ API is defined by all of the .h files in |
|
|
|
|
`upb/` except `.int.h` files (which are internal-only). |
|
|
|
|
upb_proto_library( |
|
|
|
|
name = "foo_upbproto", |
|
|
|
|
deps = [":foo_proto"], |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
## Lua bindings |
|
|
|
|
cc_library( |
|
|
|
|
name = "lib_that_uses_protos", |
|
|
|
|
srcs = ["lib_that_uses_protos.cc"], |
|
|
|
|
deps = [":foo_upbproto"], |
|
|
|
|
) |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
Lua bindings provide μpb's functionality to Lua programs. |
|
|
|
|
The bindings target Lua 5.1, Lua 5.2, LuaJIT, and (soon) Lua 5.3. |
|
|
|
|
Then in your `.c` file you can #include the generated header: |
|
|
|
|
|
|
|
|
|
To build the Lua bindings, the Lua libraries must be installed. Once |
|
|
|
|
they are installed, run: |
|
|
|
|
```c |
|
|
|
|
#include "foo.upb.h" |
|
|
|
|
|
|
|
|
|
$ make lua |
|
|
|
|
/* Insert code that uses generated types. */ |
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
Note that if the Lua headers are not in a standard place, you may |
|
|
|
|
need to pass custom flags: |
|
|
|
|
## Old "handlers" interfaces |
|
|
|
|
|
|
|
|
|
$ make lua USER_CPPFLAGS=`pkg-config lua5.2 --cflags` |
|
|
|
|
This library contains several semi-deprecated interfaces (see BUILD |
|
|
|
|
file for more info about which interfaces are deprecated). These |
|
|
|
|
deprecated interfaces are still used in some significant projects, |
|
|
|
|
such as the Ruby and PHP C bindings for protobuf in the [main protobuf |
|
|
|
|
repo](https://github.com/protocolbuffers/protobuf). The goal is to |
|
|
|
|
migrate the Ruby/PHP bindings to use the newer, simpler interfaces |
|
|
|
|
instead. Please do not use the old interfaces in new code. |
|
|
|
|
|
|
|
|
|
To test the Lua bindings: |
|
|
|
|
## Lua bindings |
|
|
|
|
|
|
|
|
|
$ make testlua |
|
|
|
|
This repo has some Lua bindings for the core library. These are |
|
|
|
|
experimental and very incomplete. These are currently included in |
|
|
|
|
order to validate that the C API is suitable for wrapping. As the |
|
|
|
|
project matures these Lua bindings may become publicly available. |
|
|
|
|
|
|
|
|
|
## Contact |
|
|
|
|
|
|
|
|
|