Skip to content
Gregory Szorc edited this page Oct 9, 2010 · 7 revisions

How it Works

lua-protobuf provides a plugin for the protoc compiler (that ships with protocol buffers). This plugin receives your protocol buffer definitions and tells protoc to write out new C files which define bindings that allow your protocol buffer messages to be used in Lua. Protocol buffer message instances are treated as Lua userdata types and all calls in Lua land get proxied to the C++ code, which is also generated by protoc.

API

See Lua API and C API for details of the API produced by the compiler plugin.

State of the Project

Currently, the project provides an interface to protocol buffer messages and nothing more. Streams, low-level parsing, descriptors, and other features are absent. This may change as the project matures.

There are also some message features not yet supported. Consult Lua API for details of what is and isn't supported.

The project is also still in its infancy. Implementation details are likely to change, so think twice before spending too much work coding against the API this project provides.

Important Considerations

lua-protobuf generates C/C++ code that interfaces with the C API of the reference Lua implementation available at http://www.lua.org/. There are various (implementations)[http://lua-users.org/wiki/LuaImplementations] of Lua and many don't expose the same C API that lua-protobuf utilizes. Therefore, you won't be able to use lua-protobuf with these implementations.

An ideal (in terms of compatibility) Lua protocol buffer implementation would be written in 100% Lua so it could run on all interpreters. However, this would be considerable more work, as all the protocol buffer functionality would need to be ported to Lua.

Known Issues

Number Type Representations

By default, Lua represents all numbers as double-precision floating-point. In C, this is a double type. The Lua C API can cast numbers to the types lua_Number and lua_Integer. The former is the type Lua is using under-the-hood. The latter is likely a signed 32 or 64 bit integer (likely depending on the system's architecture). All the gory details can be found in luaconf.h in the Lua source distribution.

This causes trouble for interacting with protocol buffers. Do we extract everything as lua_Number and let the compiler convert to uint64 and other types? Or, do we detect which conversations are "safe" for a given machine and generate the appropriate source code?

I'm not sure yet. For now, all 32 and 64 bit integer protocol buffer fields are converted to lua_Integer and passed to the protocol buffer C++ API. This results in numerous compiler warnings for possible truncation. This naive solution is bad and will change.

Requiring Package Field

Currently, the protoc plugin heavily relies on the .proto file's package. This is bad because the package identifier is supposed to be optional.

For now, you'll need a package in every .proto file you wish to use with lua-protobuf.

Incorrect Module Loading

The mechanism by which Lua types are registered with Lua is wrong. Specifically, it doesn't follow the convention where function names should be named luaopen*. This means that things need to be loaded in C land since they can't be loaded from Lua's autodiscovery routines.

No Table Access to Fields

It would be convenient to access protocol buffer message fields using the Lua table syntax instead of calling functions. This will make its way into a future version.

Embedded Message References and Clear()

When clear() is called on an embedded message field or on a message, the memory address of a previously returned embedded message is invalidated. In Lua, we currently don't track this. So, if things are executed in the correct order, segmentation faults are likely.

The Lua userdata type will be updated in a future version to track the parent message and compare pointers so operations against expired embedded messages are detected.

Frequently Asked Questions

Relationship to Other Lua Implementations

There exists at least one other project providing protocol buffer support for Lua, protoc-gen-lua.

The major difference is that project is written in mostly Lua (only the low-level packing/unpacking is in C) and this project is written in C/C++. There are also various levels of support for different protocol buffer concepts.

If you programming in a nearly complete Lua environment, either project will work. But, you may want to start with the other project, protoc-gen-lua, as it might be simpler to use. However, if you are using Lua from C/C++ and want to pass protocol buffer messages between it and Lua, this project might be better, especially if performance is important or if you want to share a message instance across both environments. The reason is is that to pass protocol buffer messages between C and protoc-gen-lua will require you to serialiaze and deserialize the message. This project, by contrast, wraps the C++ data type and passes a pointer to Lua. No additional serialization is required. That being said, protocol buffers are extremely fast, so it isn't as bad as it sounds.

At this time, no comparative benchmarks between the two projects have been performed. C/C++ is typically faster than Lua. But, Lua interpreters like LuaJIT can perform some functionality at roughly the same speed as C/C++, so it could be an interesting comparison.

Should I Use This?

The project is still very young and the API may change. While the plugin is definitely usable, you may want to hold off using it if refactoring to a new API will be resource intensive.

It is Written in Python?!

It is, at least for now. Before this project, there was no way to consume protocol buffers in Lua. The protoc plugin architecture requires parsing protocol buffer messages. So, there was a choice: write the Lua plugin in another language or write my own .proto file parser in Lua. The latter is a bad idea (tm) for many reasons, so it was decided to write the plugin in the easiest to use of the 3 officially supported protocol buffer languages, Python.

Why Don't You Support Protocol Buffers Component X (Streams, etc)?

This would be a significant undertaking and I (IndyGreg), have no desire to do it because I don't need it. You may be interested in protoc-gen-lua, which appears to provide a lot of additional functionality.