package ocaml-protoc-plugin

  1. Overview
  2. Docs
Plugin for protoc protobuf compiler to generate ocaml definitions from a .proto file







The plugin generates ocaml type definitions, serialization and deserialization functions from a protobuf file. The types generated aims to create ocaml idiomatic types;

  • messages are mapped into modules
  • oneof constructs are mapped to polymorphic variants
  • enums are mapped to adt's
  • map types are mapped to assoc lists
  • all integer types are mapped to int
  • all floating point types are mapped to float.
  • packages are mapped to nested modules

Published: 27 Sep 2019


Ocaml protoc plugin

The goal of Ocaml protoc plugin is to create an up to date plugin for the google protobuf compiler (protoc) to generate ocaml types and serialization and de-serialization.

The main features include:

  • Messages are mapped to idiomatic OCaml types

  • Support service descriptions

  • proto3 compatibility

Comparisson with other OCaml protobuf handlers.

Feature ocaml-protoc ocaml-pb-plugin ocaml-protoc-plugin
Ocaml types Supported Defined runtime Supported
Service endpoints Not supported N/A Supported
proto3 Partly supported supported Supported

(ocaml-protoc release 1.2.0 does not yet fully support proto3, the master branch does, however)


Basic types are mapped trivially to ocaml types:

Primitive types:

Protobuf Type Ocaml type
Integers int
Real float
string string
bytes bytes

A message declaration is compiled to a module with a record type t. However, messages without any fields are mapped to unit.

Packages are trivially mapped to modules. Included proto files (.proto) are assumed to have been compiled to .ml, and types in included proto files are referenced by their fill name.

Compound types are mapped like:

Protobuf Type Ocaml type
oneof Polymorphic variants: [ Field1 of fieldtype1, Field1 of fieldtype2 ]
repeated 'a 'a list
message message option
enum Abstract data types: Enum1, Enum2, Enum3
map<'a, 'b> ('a * 'b) list


If the plugin is available in the path as protoc-gen-ocaml, then you can generate the ocaml code by running

  protoc --ocaml_out=. --ocaml_opt=<options> file.proto

Options control the code generated.

Option Description Example
annot Type annotations. annot=[@@deriving show]
debug Enable debugging debug
open Add open at top of generated files. May be given multiple times open=Base.Sexp

Parameters are seperated by ;

If protoc-gen-ocaml is not located in the path, it is possible to specify the exact path to the plugin:

protoc --plugin=protoc-gen-ocaml=../plugin/ocaml-protocol-plugin.exe --ocaml_out=. <file>.proto

Older versions of protoc

It seems that the --ocaml_opt flag may not be supported by older versions of the proto compiler. As an alternative, options can also be passed with the --ocaml_out flag:

protoc --plugin=protoc-gen-ocaml=../plugin/ocaml.exe --ocaml_out=annot=debug;[@@deriving show { with_path = false }, eq]:. <file>.proto

Using dune

Below is a dune rule for generating code for test.proto:

  (:proto test.proto))
  (run protoc -I .  "--ocaml_opt=annot=[@@deriving show { with_path = false }, eq]" --ocaml_out=. %{proto})))

Service interface

!Note this is deprecated, and will change

module IO = struct
  'a deferred;

val call: (string->string IO.deferred) -> request_type ->
  (response_type, [> `Some_error_type)] result IO.deferred

val service: (request_type -> (response_type, [> ]) result
IO.deferred]) -> string -> string, [> ] result IO.Deferred

The call function will take a string -> string function, which implement message sending -> receiving.

The service function is a string -> string function which takes a handler working over the actual message types.

Of course the the functions work of an IO monad.

Dependencies (10)

  1. ppx_inline_test < "v0.14"
  2. ppx_expect < "v0.14"
  3. ppx_deriving
  4. ppx_let < "v0.14"
  5. ocplib-endian
  6. ocaml-protoc build
  7. ocaml >= "4.07.0"
  8. dune >= "1.10"
  9. conf-protoc
  10. base < "v0.14"

Dev Dependencies


Used by