~bigbes/tarantool

tarantool-protobuf

ref: 48ef418028fc02aaa2348f6ba34c988c4fd21100 tarantool-protobuf/docs/howto/01-first-message.md -rw-r--r-- 3.5 KiB
48ef4180 — Eugene Blikh beads: close a6n + memory note on ffi.cast cdata allocation 2 months ago

#How-to: your first message, end-to-end

Goal: take a .proto file from zero to a Tarantool process encoding and decoding it.

#What you need

  • tarantool (3.x, with LuaJIT 2.1)
  • protoc (Google's compiler — brew install protobuf on macOS, apt install protobuf-compiler on Debian/Ubuntu)
  • The protoc-gen-tarantool binary on PATH — build it with just build from this repo, or go build -o protoc-gen-tarantool ./cmd/protoc-gen-tarantool and copy the result.

#1. Write the proto

The example file lives at examples/proto/quickstart.proto:

syntax = "proto3";

package quickstart;

enum Role {
  ROLE_UNSPECIFIED = 0;
  USER = 1;
  ADMIN = 2;
}

message User {
  int32 id = 1;
  string name = 2;
  Role role = 3;
  repeated string emails = 4;
}

#2. Generate the Lua module

protoc --tarantool_out=./out -I. examples/proto/quickstart.proto

This drops out/quickstart/quickstart_pb.lua. The output path mirrors the proto package (package quickstart;quickstart/).

To change where it lands, see how-to: module layout.

#3. Round-trip in Tarantool

The generated module requires pb from runtime/pb/, so point LUA_PATH at both runtime/ and the generated out/ directory:

tarantool -e '
package.path = "./runtime/?/init.lua;./runtime/?.lua;./out/?.lua;./out/?/init.lua;" .. package.path

local qs = require("quickstart.quickstart_pb")

-- Encode a Lua table to wire bytes.
local bytes = qs.User_encode({
    id = 7,
    name = "Alice",
    role = qs.Role.ADMIN,
    emails = {"a@x", "b@x"},
})
print(#bytes .. " bytes")

-- Decode back.
local user = qs.User_decode(bytes)
print(user.id, user.name, user.role, user.emails[1], user.emails[2])

-- Pretty-print with text format (mainline-protoc compatible).
print(qs.User_text(user))
'

Expected output:

21 bytes
7	Alice	2	a@x	b@x
id: 7
name: "Alice"
role: ADMIN
emails: "a@x"
emails: "b@x"

#4. Common issues

module 'pb' not foundLUA_PATH doesn't include the runtime/ directory. The two patterns you need are ./runtime/?/init.lua (for require('pb')runtime/pb/init.lua) and ./runtime/?.lua (for sibling modules like require('pb.wire')).

module 'quickstart.quickstart_pb' not found — generated path isn't on LUA_PATH. Add ./out/?.lua;./out/?/init.lua; (or whatever directory you passed to --tarantool_out).

expected cdata int64_t, got number — you passed a Lua number to a int64 / uint64 / fixed64 / sfixed64 / sint64 field. Use pb.to_uint64(value) or pb.to_int64(value) to coerce:

local pb = require("pb")
qs.User_encode({id = pb.to_int64(7)})

(The User.id example above is int32, which accepts a plain Lua number — only 64-bit-typed fields need the coercion.)

protoc-gen-tarantool: program not found or is not executableprotoc couldn't find the plugin on PATH. Either copy the binary to a directory on PATH, or invoke protoc with an explicit --plugin= flag:

protoc --plugin=protoc-gen-tarantool=./protoc-gen-tarantool \
       --tarantool_out=./out ...

#What's next