[Tarantool-patches] [PATCH] Introduce unified Lua ffi.cdef builder

Sergey Voinov sergeiv at tarantool.org
Tue Jan 21 16:23:12 MSK 2020


Lua ffi is quite fast and simple mechanism allowing to call
C functions directly, without using Lua C API. It is usually
faster, sometimes much faster. But ffi requires to define all
the C methods again in a Lua file in ffi.cdef function. It is
as bad as any other code duplication - when the original API
is changed, a one could forget to update Lua files and ffi.cdef
arguments. It is especially painful, when ffi C definition is really big.

The goal is to introduce a mechanism to generate ffi C definitions.

The implementation.
===================

The mechanism to generate ffi C definitions is similar to how
module.h is generated. There is a script extra/fficdefgen which
parses specified set of C headers and produces content for ffi.cdef.
The idea is similar to module.h generation: use comment tags in
C headers to rip off the content between two tags:
/* \cond ffi */
and
/* \endcond ffi */
Everything between these tags will be the output of this script.

The output of extra/fficdefgen is placed into src/lua/load_ffi_defs.lua file.
This file contains three parts:
1. Header - from src/lua/load_ffi_defs.header.lua
2. Output from extra/fficdefgen
3. Footer - from src/lua/load_ffi_defs.footer.lua
So we can add some C definitions manually before and after those
which are automatically generated. This is important since
some definitions cannot be added automatically, e.g. from system
headers, submodules and containing identifiers which are Lua keywords
(see comments in load_ffi_defs.header.lua and load_ffi_defs.footer.lua).

load_ffi_defs.lua file is produced by rebuild_module_fficdef function in
cmake/fficdef.cmake CMake script.

load_ffi_defs.lua is then compiled into src/lua/load_ffi_defs.lua.c source
(see lua_sources list in CMakeLists.txt).

load_ffi_defs.lua content is referenced in lua_modules in src/lua/init.c
and is loaded at startup with all ffi.cdef definitions gathered from
specified C headers and load_ffi_defs.header.lua/load_ffi_defs.footer.lua.

So, what we need to include in C headers are the tags.
But how do we know which C headers to include into load_ffi_defs.lua?
There is a list (similar to one for module.h) in src/CMakeLists.txt file
called fficdef_headers. rebuild_module_fficdef function is also
called from CMakeLists.txt.

Important notice. For now, only core C headers are included into
fficdef_headers list. This means that headers from Tarantool
submodules are not included and some C definitions are thereby
manually placed into load_ffi_defs.header.lua/load_ffi_defs.footer.lua.

Currently, this ffi.cdef builder is kind of internal mechanism, but
can be used by anyone following the scenario:
1. Include /* \cond ffi */ and /* \endcond ffi */ tags into needed C header.
2. Include needed C header in fficdef_headers list in CMakeLists.txt.

Closes: #4202
---
 issue: https://github.com/tarantool/tarantool/issues/4202
 branch: https://github.com/tarantool/tarantool/tree/servoin/gh-4202-ffi-cdef-builder
 .gitignore                       |   1 +
 CMakeLists.txt                   |   1 +
 cmake/fficdef.cmake              |  37 ++++++
 extra/fficdefgen                 |  16 +++
 src/CMakeLists.txt               |  39 +++++++
 src/box/box.h                    |   3 +
 src/box/index.h                  |   2 +
 src/box/lua/schema.lua           | 101 -----------------
 src/box/lua/tuple.lua            |  52 ---------
 src/box/port.h                   |   3 +
 src/box/schema.h                 |   8 ++
 src/box/space.h                  |   8 ++
 src/box/tuple.h                  |  11 ++
 src/box/txn.h                    |   6 +
 src/box/user_def.h               |   1 +
 src/crc32.h                      |   4 +
 src/lib/core/clock.h             |   2 +
 src/lib/core/coio.h              |   3 +
 src/lib/core/decimal.h           |   4 +
 src/lib/core/diag.h              |   4 +
 src/lib/core/exception.h         |   4 +
 src/lib/core/fiber.h             |   4 +
 src/lib/core/mp_decimal.h        |   4 +
 src/lib/core/port.h              |   4 +
 src/lib/core/random.h            |   4 +
 src/lib/core/reflection.h        |   8 ++
 src/lib/core/say.h               |  26 +++++
 src/lib/crypto/crypto.h          |  14 +++
 src/lib/csv/csv.h                |  16 +++
 src/lib/salad/guava.h            |   4 +
 src/lib/swim/swim.h              |  12 ++
 src/lib/swim/swim_constants.h    |   8 ++
 src/lib/uri/uri.h                |   8 ++
 src/lib/uuid/tt_uuid.h           |   8 ++
 src/lua/buffer.lua               |  63 -----------
 src/lua/clock.lua                |  11 --
 src/lua/crypto.lua               |  66 -----------
 src/lua/csv.lua                  |  48 --------
 src/lua/digest.h                 |   4 +
 src/lua/digest.lua               |  26 -----
 src/lua/env.lua                  |   7 --
 src/lua/errno.lua                |   4 -
 src/lua/error.lua                |  30 -----
 src/lua/fiber.lua                |  10 --
 src/lua/fio.lua                  |   6 -
 src/lua/iconv.lua                |   8 --
 src/lua/init.c                   |   2 +
 src/lua/init.h                   |   4 +
 src/lua/init.lua                 |  40 -------
 src/lua/load_ffi_defs.footer.lua | 155 +++++++++++++++++++++++++
 src/lua/load_ffi_defs.header.lua | 187 +++++++++++++++++++++++++++++++
 src/lua/log.lua                  |  48 --------
 src/lua/msgpackffi.lua           |  19 ----
 src/lua/pwd.lua                  |  83 --------------
 src/lua/socket.h                 |   4 +
 src/lua/socket.lua               |  45 --------
 src/lua/string.h                 |   4 +
 src/lua/string.lua               |  12 --
 src/lua/swim.lua                 | 113 -------------------
 src/lua/title.lua                |  12 --
 src/lua/uri.lua                  |  28 -----
 src/lua/utils.h                  |   2 +
 src/lua/uuid.lua                 |  27 -----
 src/main.h                       |   4 +
 src/scramble.h                   |   4 +
 src/title.h                      |   4 +
 test/app/uuid.result             |   2 +-
 67 files changed, 652 insertions(+), 860 deletions(-)
 create mode 100644 cmake/fficdef.cmake
 create mode 100755 extra/fficdefgen
 create mode 100644 src/lua/load_ffi_defs.footer.lua
 create mode 100755 src/lua/load_ffi_defs.header.lua

diff --git a/.gitignore b/.gitignore
index b8ffaca6d..326843972 100644
--- a/.gitignore
+++ b/.gitignore
@@ -84,6 +84,7 @@ src/lua/*.lua.c
 src/box/lua/*.lua.c
 src/tarantool
 src/module.h
+src/lua/load_ffi_defs.lua
 tarantool-*.tar.gz
 test/lib/
 test/unit/*.test
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ca968eb8d..fe6bc817f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -70,6 +70,7 @@ include(cmake/simd.cmake)
 include(cmake/atomic.cmake)
 include(cmake/profile.cmake)
 include(cmake/module.cmake)
+include(cmake/fficdef.cmake)
 include(cmake/thread.cmake)
 
 set(CMAKE_REQUIRED_DEFINITIONS "-D_GNU_SOURCE")
diff --git a/cmake/fficdef.cmake b/cmake/fficdef.cmake
new file mode 100644
index 000000000..596d0d927
--- /dev/null
+++ b/cmake/fficdef.cmake
@@ -0,0 +1,37 @@
+# A helper function for unified Lua ffi.cdef builder
+function(rebuild_module_fficdef)
+    set (dstfile "${CMAKE_CURRENT_BINARY_DIR}/lua/load_ffi_defs.lua")
+    set (tmpfile "${dstfile}.new")
+    set (headers)
+    # Get absolute path for header files (required of out-of-source build)
+    foreach (header ${ARGN})
+        if (IS_ABSOLUTE ${header})
+            list(APPEND headers ${header})
+        else()
+            list(APPEND headers ${CMAKE_CURRENT_SOURCE_DIR}/${header})
+        endif()
+    endforeach()
+
+    set (cflags ${CMAKE_C_FLAGS})
+    separate_arguments(cflags)
+    # Pass sysroot settings on OSX
+    if (NOT "${CMAKE_OSX_SYSROOT}" STREQUAL "")
+        set (cflags ${cflags} ${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT})
+    endif()
+    add_custom_command(OUTPUT ${dstfile}
+        COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/lua/load_ffi_defs.header.lua > ${tmpfile}
+        COMMAND cat ${headers} | ${CMAKE_SOURCE_DIR}/extra/fficdefgen >> ${tmpfile}
+        COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/lua/load_ffi_defs.footer.lua >> ${tmpfile}
+        COMMAND ${CMAKE_COMMAND} -E copy_if_different ${tmpfile} ${dstfile}
+        COMMAND ${CMAKE_COMMAND} -E remove ${errcodefile} ${tmpfile}
+        DEPENDS ${CMAKE_SOURCE_DIR}/extra/fficdefgen
+                ${CMAKE_CURRENT_SOURCE_DIR}/lua/load_ffi_defs.header.lua
+                ${CMAKE_CURRENT_SOURCE_DIR}/lua/load_ffi_defs.footer.lua
+                ${CMAKE_SOURCE_DIR}/src/box/errcode.h
+                ${headers}
+        )
+
+    add_custom_target(fficdef ALL DEPENDS ${dstfile})
+    install(FILES ${dstfile} DESTINATION ${MODULE_INCLUDEDIR})
+endfunction()
+set_source_files_properties("${CMAKE_CURRENT_BINARY_DIR}/lua/load_ffi_cdef.lua" PROPERTIES GENERATED HEADER_FILE_ONLY)
diff --git a/extra/fficdefgen b/extra/fficdefgen
new file mode 100755
index 000000000..8a63687d3
--- /dev/null
+++ b/extra/fficdefgen
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# This script generates output for unified FFI cdef builder
+# 1. Include only lines between /** \cond ffi */ and /** \endcond ffi */
+# 2. Remove API_EXPORT macro
+# 3. Remove C preprocessor commands (#if defined/#endif)
+# 4. Remove CFORMAT macro
+# 5. Rename end to epos
+# 6. Remove MP_PROTO macro
+
+sed -n '/^\/\*\* \\cond ffi \*\/$/,/^\/\*\* \\endcond ffi \*\/$/P' | \
+sed -E 's/([[:space:]]*)API_EXPORT[[:space:]]+/\1/g' | \
+sed -n -e '/^#if defined/,/^#endif/!p' | \
+sed -E 's/CFORMAT\(.*\)//g' | \
+sed -E 's/\*end;/\*epos;/' |
+sed 's/MP_PROTO//g'
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e12de6005..eb3056453 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -51,6 +51,7 @@ lua_source(lua_sources ../third_party/luafun/fun.lua)
 lua_source(lua_sources lua/httpc.lua)
 lua_source(lua_sources lua/iconv.lua)
 lua_source(lua_sources lua/swim.lua)
+lua_source(lua_sources lua/load_ffi_defs.lua)
 # LuaJIT jit.* library
 lua_source(lua_sources "${CMAKE_BINARY_DIR}/third_party/luajit/src/jit/bc.lua")
 lua_source(lua_sources "${CMAKE_BINARY_DIR}/third_party/luajit/src/jit/bcsave.lua")
@@ -158,6 +159,44 @@ set(api_headers
 )
 rebuild_module_api(${api_headers})
 
+set(fficdef_headers
+    ${CMAKE_SOURCE_DIR}/src/title.h
+    ${CMAKE_SOURCE_DIR}/src/box/box.h
+    ${CMAKE_SOURCE_DIR}/src/box/index.h
+    ${CMAKE_SOURCE_DIR}/src/box/port.h
+    ${CMAKE_SOURCE_DIR}/src/box/schema.h
+    ${CMAKE_SOURCE_DIR}/src/box/space.h
+    ${CMAKE_SOURCE_DIR}/src/box/tuple.h
+    ${CMAKE_SOURCE_DIR}/src/box/txn.h
+    ${CMAKE_SOURCE_DIR}/src/crc32.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/clock.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/coio.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/diag.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/exception.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/fiber.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/port.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/random.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/reflection.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/say.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/decimal.h
+    ${CMAKE_SOURCE_DIR}/src/lib/core/mp_decimal.h
+    ${CMAKE_SOURCE_DIR}/src/lib/crypto/crypto.h
+    ${CMAKE_SOURCE_DIR}/src/lib/csv/csv.h
+    ${CMAKE_SOURCE_DIR}/src/lib/salad/guava.h
+    ${CMAKE_SOURCE_DIR}/src/lib/swim/swim.h
+    ${CMAKE_SOURCE_DIR}/src/lib/swim/swim_constants.h
+    ${CMAKE_SOURCE_DIR}/src/lib/uri/uri.h
+    ${CMAKE_SOURCE_DIR}/src/lib/uuid/tt_uuid.h
+    ${CMAKE_SOURCE_DIR}/src/lua/digest.h
+    ${CMAKE_SOURCE_DIR}/src/lua/init.h
+    ${CMAKE_SOURCE_DIR}/src/lua/socket.h
+    ${CMAKE_SOURCE_DIR}/src/lua/string.h
+    ${CMAKE_SOURCE_DIR}/src/lua/utils.h
+    ${CMAKE_SOURCE_DIR}/src/main.h
+    ${CMAKE_SOURCE_DIR}/src/scramble.h
+)
+rebuild_module_fficdef(${fficdef_headers})
+
 if (NOT TARGET_OS_DEBIAN_FREEBSD)
     if (TARGET_OS_FREEBSD)
         set_source_files_properties(
diff --git a/src/box/box.h b/src/box/box.h
index ccd527bd5..ddd5b8f83 100644
--- a/src/box/box.h
+++ b/src/box/box.h
@@ -241,6 +241,8 @@ extern "C" {
 
 typedef struct tuple box_tuple_t;
 
+/** \cond ffi */
+
 /* box_select is private and used only by FFI */
 API_EXPORT int
 box_select(uint32_t space_id, uint32_t index_id,
@@ -248,6 +250,7 @@ box_select(uint32_t space_id, uint32_t index_id,
 	   const char *key, const char *key_end,
 	   struct port *port);
 
+/** \endcond ffi */
 /** \cond public */
 
 /*
diff --git a/src/box/index.h b/src/box/index.h
index 86148023f..0c1288b21 100644
--- a/src/box/index.h
+++ b/src/box/index.h
@@ -47,6 +47,7 @@ struct key_def;
 struct info_handler;
 
 /** \cond public */
+/** \cond ffi */
 
 typedef struct tuple box_tuple_t;
 typedef struct key_def box_key_def_t;
@@ -209,6 +210,7 @@ char *
 box_tuple_extract_key(box_tuple_t *tuple, uint32_t space_id,
 		      uint32_t index_id, uint32_t *key_size);
 
+/** \endcond ffi */
 /** \endcond public */
 
 /**
diff --git a/src/box/lua/schema.lua b/src/box/lua/schema.lua
index e898c3aa6..3ffe27d8d 100644
--- a/src/box/lua/schema.lua
+++ b/src/box/lua/schema.lua
@@ -25,107 +25,6 @@ assert(tuple_encode ~= nil and tuple_bless ~= nil and is_tuple ~= nil)
 local INT64_MIN = tonumber64('-9223372036854775808')
 local INT64_MAX = tonumber64('9223372036854775807')
 
-ffi.cdef[[
-    struct space *space_by_id(uint32_t id);
-    extern uint32_t box_schema_version();
-    void space_run_triggers(struct space *space, bool yesno);
-    size_t space_bsize(struct space *space);
-
-    typedef struct tuple box_tuple_t;
-    typedef struct iterator box_iterator_t;
-
-    /** \cond public */
-    box_iterator_t *
-    box_index_iterator(uint32_t space_id, uint32_t index_id, int type,
-                       const char *key, const char *key_end);
-    int
-    box_iterator_next(box_iterator_t *itr, box_tuple_t **result);
-    void
-    box_iterator_free(box_iterator_t *itr);
-    /** \endcond public */
-    /** \cond public */
-    ssize_t
-    box_index_len(uint32_t space_id, uint32_t index_id);
-    ssize_t
-    box_index_bsize(uint32_t space_id, uint32_t index_id);
-    int
-    box_index_random(uint32_t space_id, uint32_t index_id, uint32_t rnd,
-                     box_tuple_t **result);
-    int
-    box_index_get(uint32_t space_id, uint32_t index_id, const char *key,
-                  const char *key_end, box_tuple_t **result);
-    int
-    box_index_min(uint32_t space_id, uint32_t index_id, const char *key,
-                  const char *key_end, box_tuple_t **result);
-    int
-    box_index_max(uint32_t space_id, uint32_t index_id, const char *key,
-                  const char *key_end, box_tuple_t **result);
-    ssize_t
-    box_index_count(uint32_t space_id, uint32_t index_id, int type,
-                    const char *key, const char *key_end);
-    /** \endcond public */
-    /** \cond public */
-    bool
-    box_txn();
-    int64_t
-    box_txn_id();
-    int
-    box_txn_begin();
-    /** \endcond public */
-    typedef struct txn_savepoint box_txn_savepoint_t;
-
-    box_txn_savepoint_t *
-    box_txn_savepoint();
-
-    int
-    box_txn_rollback_to_savepoint(box_txn_savepoint_t *savepoint);
-
-    struct port_tuple_entry {
-        struct port_tuple_entry *next;
-        struct tuple *tuple;
-    };
-
-    struct port_tuple {
-        const struct port_vtab *vtab;
-        size_t size;
-        struct port_tuple_entry *first;
-        struct port_tuple_entry *last;
-        struct port_tuple_entry first_entry;
-    };
-
-    void
-    port_destroy(struct port *port);
-
-    int
-    box_select(uint32_t space_id, uint32_t index_id,
-               int iterator, uint32_t offset, uint32_t limit,
-               const char *key, const char *key_end,
-               struct port *port);
-
-    void password_prepare(const char *password, int len,
-                          char *out, int out_len);
-
-    enum priv_type {
-        PRIV_R = 1,
-        PRIV_W = 2,
-        PRIV_X = 4,
-        PRIV_S = 8,
-        PRIV_U = 16,
-        PRIV_C = 32,
-        PRIV_D = 64,
-        PRIV_A = 128,
-        PRIV_REFERENCE = 256,
-        PRIV_TRIGGER = 512,
-        PRIV_INSERT = 1024,
-        PRIV_UPDATE = 2048,
-        PRIV_DELETE = 4096,
-        PRIV_GRANT = 8192,
-        PRIV_REVOKE = 16384,
-        PRIV_ALL  = 4294967295
-    };
-
-]]
-
 box.priv = {
     ["R"] = builtin.PRIV_R,
     ["W"] = builtin.PRIV_W,
diff --git a/src/box/lua/tuple.lua b/src/box/lua/tuple.lua
index a25a28987..5d3c34bd4 100644
--- a/src/box/lua/tuple.lua
+++ b/src/box/lua/tuple.lua
@@ -7,58 +7,6 @@ local fun = require('fun')
 local buffer = require('buffer')
 local internal = require('box.internal')
 
-ffi.cdef[[
-/** \cond public */
-
-typedef struct tuple box_tuple_t;
-
-int
-box_tuple_ref(box_tuple_t *tuple);
-
-void
-box_tuple_unref(box_tuple_t *tuple);
-
-uint32_t
-box_tuple_field_count(box_tuple_t *tuple);
-
-size_t
-box_tuple_bsize(box_tuple_t *tuple);
-
-ssize_t
-box_tuple_to_buf(box_tuple_t *tuple, char *buf, size_t size);
-
-const char *
-box_tuple_field(box_tuple_t *tuple, uint32_t i);
-
-typedef struct tuple_iterator box_tuple_iterator_t;
-
-box_tuple_iterator_t *
-box_tuple_iterator(box_tuple_t *tuple);
-
-void
-box_tuple_iterator_free(box_tuple_iterator_t *it);
-
-uint32_t
-box_tuple_position(box_tuple_iterator_t *it);
-
-void
-box_tuple_rewind(box_tuple_iterator_t *it);
-
-const char *
-box_tuple_seek(box_tuple_iterator_t *it, uint32_t field_no);
-
-const char *
-box_tuple_next(box_tuple_iterator_t *it);
-
-/** \endcond public */
-
-box_tuple_t *
-box_tuple_update(box_tuple_t *tuple, const char *expr, const char *expr_end);
-
-box_tuple_t *
-box_tuple_upsert(box_tuple_t *tuple, const char *expr, const char *expr_end);
-]]
-
 local builtin = ffi.C
 
 local tuple_t = ffi.typeof('box_tuple_t')
diff --git a/src/box/port.h b/src/box/port.h
index 9d3d02b3c..a7bc53afe 100644
--- a/src/box/port.h
+++ b/src/box/port.h
@@ -40,6 +40,8 @@ extern "C" {
 
 struct tuple;
 
+/** \cond ffi */
+
 struct port_tuple_entry {
 	struct port_tuple_entry *next;
 	struct tuple *tuple;
@@ -55,6 +57,7 @@ struct port_tuple {
 	struct port_tuple_entry *last;
 	struct port_tuple_entry first_entry;
 };
+/** \endcond ffi */
 static_assert(sizeof(struct port_tuple) <= sizeof(struct port),
 	      "sizeof(struct port_tuple) must be <= sizeof(struct port)");
 
diff --git a/src/box/schema.h b/src/box/schema.h
index 7802941ef..c8d966c2c 100644
--- a/src/box/schema.h
+++ b/src/box/schema.h
@@ -48,6 +48,8 @@ extern uint32_t space_cache_version;
 /** Triggers invoked after schema initialization. */
 extern struct rlist on_schema_init;
 
+/** \cond ffi */
+
 /**
  * Try to look up a space by space number in the space cache.
  * FFI-friendly no-exception-thrown space lookup function.
@@ -57,6 +59,8 @@ extern struct rlist on_schema_init;
 struct space *
 space_by_id(uint32_t id);
 
+/** \endcond ffi */
+
 /**
  * Try to look up a space by space name in the space name cache.
  *
@@ -65,9 +69,13 @@ space_by_id(uint32_t id);
 struct space *
 space_by_name(const char *name);
 
+/** \cond ffi */
+
 uint32_t
 box_schema_version();
 
+/** \endcond ffi */
+
 static inline struct space *
 space_cache_find(uint32_t id)
 {
diff --git a/src/box/space.h b/src/box/space.h
index 7926aa65e..33fd95713 100644
--- a/src/box/space.h
+++ b/src/box/space.h
@@ -267,9 +267,13 @@ space_group_id(struct space *space)
 	return space->def->opts.group_id;
 }
 
+/** \cond ffi */
+
 void
 space_run_triggers(struct space *space, bool yesno);
 
+/** \endcond ffi */
+
 /**
  * Get index by index id.
  * @return NULL if the index is not found.
@@ -330,12 +334,16 @@ index_find_unique(struct space *space, uint32_t index_id)
 	return index;
 }
 
+/** \cond ffi */
+
 /**
  * Returns number of bytes used in memory by tuples in the space.
  */
 size_t
 space_bsize(struct space *space);
 
+/** \endcond ffi */
+
 /** Get definition of the n-th index of the space. */
 struct index_def *
 space_index_def(struct space *space, int n);
diff --git a/src/box/tuple.h b/src/box/tuple.h
index 9a8877219..b51cc7d96 100644
--- a/src/box/tuple.h
+++ b/src/box/tuple.h
@@ -88,6 +88,8 @@ typedef struct tuple_format box_tuple_format_t;
 box_tuple_format_t *
 box_tuple_format_default(void);
 
+/** \cond ffi */
+
 /**
  * Tuple
  */
@@ -149,6 +151,8 @@ box_tuple_bsize(box_tuple_t *tuple);
 ssize_t
 box_tuple_to_buf(box_tuple_t *tuple, char *buf, size_t size);
 
+/** \endcond ffi */
+
 /**
  * Return the associated format.
  * \param tuple tuple
@@ -157,6 +161,8 @@ box_tuple_to_buf(box_tuple_t *tuple, char *buf, size_t size);
 box_tuple_format_t *
 box_tuple_format(box_tuple_t *tuple);
 
+/** \cond ffi */
+
 /**
  * Return the raw tuple field in MsgPack format.
  *
@@ -263,6 +269,8 @@ box_tuple_seek(box_tuple_iterator_t *it, uint32_t fieldno);
 const char *
 box_tuple_next(box_tuple_iterator_t *it);
 
+/** \endcond ffi */
+
 /**
  * Allocate and initialize a new tuple from a raw MsgPack Array data.
  *
@@ -277,12 +285,15 @@ box_tuple_next(box_tuple_iterator_t *it);
 box_tuple_t *
 box_tuple_new(box_tuple_format_t *format, const char *data, const char *end);
 
+/** \cond ffi */
+
 box_tuple_t *
 box_tuple_update(box_tuple_t *tuple, const char *expr, const char *expr_end);
 
 box_tuple_t *
 box_tuple_upsert(box_tuple_t *tuple, const char *expr, const char *expr_end);
 
+/** \endcond ffi */
 /** \endcond public */
 
 /**
diff --git a/src/box/txn.h b/src/box/txn.h
index da12feebf..df2ce7b9b 100644
--- a/src/box/txn.h
+++ b/src/box/txn.h
@@ -494,6 +494,7 @@ txn_savepoint_release(struct txn_savepoint *svp);
  */
 
 /** \cond public */
+/** \cond ffi */
 
 /**
  * Transaction id - a non-persistent unique identifier
@@ -522,6 +523,8 @@ box_txn(void);
 API_EXPORT int
 box_txn_begin(void);
 
+/** \endcond ffi */
+
 /**
  * Commit the current transaction.
  * @retval 0 - success
@@ -550,6 +553,7 @@ API_EXPORT void *
 box_txn_alloc(size_t size);
 
 /** \endcond public */
+/** \cond ffi */
 
 typedef struct txn_savepoint box_txn_savepoint_t;
 
@@ -575,6 +579,8 @@ box_txn_savepoint(void);
 API_EXPORT int
 box_txn_rollback_to_savepoint(box_txn_savepoint_t *savepoint);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/box/user_def.h b/src/box/user_def.h
index 486a4ae50..f2c9c6e62 100644
--- a/src/box/user_def.h
+++ b/src/box/user_def.h
@@ -46,6 +46,7 @@ extern "C" {
 extern const char *CHAP_SHA1_EMPTY_PASSWORD;
 
 typedef uint16_t user_access_t;
+
 /**
  * Effective session user. A cache of user data
  * and access stored in session and fiber local storage.
diff --git a/src/crc32.h b/src/crc32.h
index c29e7fbd2..2866ccc89 100644
--- a/src/crc32.h
+++ b/src/crc32.h
@@ -37,6 +37,8 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 typedef uint32_t (*crc32_func)(uint32_t crc, const char *buf, unsigned int len);
 
 /*
@@ -45,6 +47,8 @@ typedef uint32_t (*crc32_func)(uint32_t crc, const char *buf, unsigned int len);
  */
 extern crc32_func crc32_calc;
 
+/** \endcond ffi */
+
 void crc32_init();
 
 #if defined(__cplusplus)
diff --git a/src/lib/core/clock.h b/src/lib/core/clock.h
index e31b8599a..83ae42f1a 100644
--- a/src/lib/core/clock.h
+++ b/src/lib/core/clock.h
@@ -39,6 +39,7 @@ extern "C" {
 #endif /* defined(__cplusplus) */
 
 /** \cond public */
+/** \cond ffi */
 
 double clock_realtime(void);
 double clock_monotonic(void);
@@ -50,6 +51,7 @@ uint64_t clock_monotonic64(void);
 uint64_t clock_process64(void);
 uint64_t clock_thread64(void);
 
+/** \endcond ffi */
 /** \endcond public */
 
 #if defined(__cplusplus)
diff --git a/src/lib/core/coio.h b/src/lib/core/coio.h
index 6a2337689..4622668e6 100644
--- a/src/lib/core/coio.h
+++ b/src/lib/core/coio.h
@@ -210,6 +210,8 @@ enum {
 API_EXPORT int
 coio_wait(int fd, int event, double timeout);
 
+/** \cond ffi */
+
 /**
  * Close the fd and wake any fiber blocked in
  * coio_wait() call on this fd.
@@ -217,6 +219,7 @@ coio_wait(int fd, int event, double timeout);
 API_EXPORT int
 coio_close(int fd);
 
+/** \endcond ffi */
 /** \endcond public */
 
 /**
diff --git a/src/lib/core/decimal.h b/src/lib/core/decimal.h
index 9a162c73c..febe66d04 100644
--- a/src/lib/core/decimal.h
+++ b/src/lib/core/decimal.h
@@ -231,6 +231,8 @@ decimal_len(const decimal_t *dec);
 char *
 decimal_pack(char *data, const decimal_t *dec);
 
+/** \cond ffi */
+
 /**
  * Using a packed representation of size \a len pointed to by
  * *data, unpack it to \a dec.
@@ -243,6 +245,8 @@ decimal_pack(char *data, const decimal_t *dec);
 decimal_t *
 decimal_unpack(const char **data, uint32_t len, decimal_t *dec);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/lib/core/diag.h b/src/lib/core/diag.h
index f763957c2..b5b091e53 100644
--- a/src/lib/core/diag.h
+++ b/src/lib/core/diag.h
@@ -42,6 +42,8 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 enum {
 	DIAG_ERRMSG_MAX = 512,
 	DIAG_FILENAME_MAX = 256
@@ -52,6 +54,8 @@ struct error;
 
 typedef void (*error_f)(struct error *e);
 
+/** \endcond ffi */
+
 /**
  * Error diagnostics needs to be equally usable in C and C++
  * code. This is why there is a common infrastructure for errors.
diff --git a/src/lib/core/exception.h b/src/lib/core/exception.h
index d6154eb32..9ae6786b1 100644
--- a/src/lib/core/exception.h
+++ b/src/lib/core/exception.h
@@ -53,12 +53,16 @@ extern const struct type_info type_CollationError;
 extern const struct type_info type_SwimError;
 extern const struct type_info type_CryptoError;
 
+/** \cond ffi */
+
 const char *
 exception_get_string(struct error *e, const struct method_info *method);
 
 int
 exception_get_int(struct error *e, const struct method_info *method);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 
diff --git a/src/lib/core/fiber.h b/src/lib/core/fiber.h
index faaf2e0da..0de9110e1 100644
--- a/src/lib/core/fiber.h
+++ b/src/lib/core/fiber.h
@@ -341,6 +341,8 @@ fiber_sleep(double s);
 API_EXPORT bool
 fiber_is_cancelled();
 
+/** \cond ffi */
+
 /**
  * Report loop begin time as double (cheap).
  * Uses real time clock.
@@ -369,6 +371,8 @@ fiber_clock(void);
 API_EXPORT uint64_t
 fiber_clock64(void);
 
+/** \endcond ffi */
+
 /**
  * Reschedule fiber to end of event loop cycle.
  */
diff --git a/src/lib/core/mp_decimal.h b/src/lib/core/mp_decimal.h
index 778529068..73a8a1789 100644
--- a/src/lib/core/mp_decimal.h
+++ b/src/lib/core/mp_decimal.h
@@ -38,6 +38,8 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 /**
  * \brief Calculate exact buffer size needed to store a decimal
  * pointed to by \a dec.
@@ -63,6 +65,8 @@ mp_decode_decimal(const char **data, decimal_t *dec);
 char *
 mp_encode_decimal(char *data, const decimal_t *dec);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/lib/core/port.h b/src/lib/core/port.h
index d61342287..de243e7b7 100644
--- a/src/lib/core/port.h
+++ b/src/lib/core/port.h
@@ -125,10 +125,14 @@ struct port {
 	char pad[48];
 };
 
+/** \cond ffi */
+
 /** Is not inlined just to be exported. */
 void
 port_destroy(struct port *port);
 
+/** \endcond ffi */
+
 static inline int
 port_dump_msgpack(struct port *port, struct obuf *out)
 {
diff --git a/src/lib/core/random.h b/src/lib/core/random.h
index 26109b14b..166ae298b 100644
--- a/src/lib/core/random.h
+++ b/src/lib/core/random.h
@@ -42,9 +42,13 @@ random_init(void);
 void
 random_free(void);
 
+/** \cond ffi */
+
 void
 random_bytes(char *buf, size_t size);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 }
 #endif /* extern "C" */
diff --git a/src/lib/core/reflection.h b/src/lib/core/reflection.h
index 8845726d4..23a48a10f 100644
--- a/src/lib/core/reflection.h
+++ b/src/lib/core/reflection.h
@@ -43,6 +43,8 @@ extern "C" {
 struct type_info;
 struct method_info;
 
+/** \cond ffi */
+
 /**
  * Primitive C types
  */
@@ -58,6 +60,8 @@ struct type_info {
 	const struct method_info *methods;
 };
 
+/** \endcond ffi */
+
 inline bool
 type_assignable(const struct type_info *type, const struct type_info *object)
 {
@@ -87,6 +91,8 @@ type_assignable(const struct type_info *type, const struct type_info *object)
 typedef void (type_info::*method_thiscall_f)(void);
 #endif
 
+/** \cond ffi */
+
 enum { METHOD_ARG_MAX = 8 };
 
 struct method_info {
@@ -106,6 +112,8 @@ struct method_info {
 	};
 };
 
+/** \endcond ffi */
+
 #define type_foreach_method(m, method)						\
 	for(const struct type_info *_m = (m); _m != NULL; _m = _m->parent)	\
 		for (const struct method_info *method = _m->methods;		\
diff --git a/src/lib/core/say.h b/src/lib/core/say.h
index d26c3ddef..9f55c95e0 100644
--- a/src/lib/core/say.h
+++ b/src/lib/core/say.h
@@ -45,6 +45,8 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 extern pid_t log_pid;
 
 /** \cond public */
@@ -70,6 +72,8 @@ enum say_format {
 
 extern int log_level;
 
+/** \endcond ffi */
+
 static inline bool
 say_log_level_is_enabled(int level)
 {
@@ -77,15 +81,20 @@ say_log_level_is_enabled(int level)
 }
 
 /** \endcond public */
+/** \cond ffi */
 
 extern enum say_format log_format;
 
+/** \endcond ffi */
+
 enum say_syslog_server_type {
 	SAY_SYSLOG_DEFAULT,
 	SAY_SYSLOG_UNIX,
 	SAY_SYSLOG_REMOTE
 };
 
+/** \cond ffi */
+
 enum say_logger_type {
 	/**
 	 * Before the app server core is initialized, we do not
@@ -106,6 +115,8 @@ enum say_logger_type {
 	SAY_LOGGER_SYSLOG
 };
 
+/** \endcond ffi */
+
 enum syslog_facility {
 	SYSLOG_KERN = 0,
 	SYSLOG_USER,
@@ -195,6 +206,8 @@ int
 log_say(struct log *log, int level, const char *filename,
 	int line, const char *error, const char *format, ...);
 
+/** \cond ffi */
+
 /**
  * Default logger type info.
  * @retval say_logger_type.
@@ -202,6 +215,8 @@ log_say(struct log *log, int level, const char *filename,
 enum say_logger_type
 log_type();
 
+/** \endcond ffi */
+
 /**
  * Set log level. Can be used dynamically.
  *
@@ -220,6 +235,8 @@ log_set_level(struct log *log, enum say_level level);
 void
 log_set_format(struct log *log, log_format_func_t format_func);
 
+/** \cond ffi */
+
 /**
  * Set log level for the default logger. Can be used dynamically.
  * @param format	constant level
@@ -236,6 +253,8 @@ say_set_log_level(int new_level);
 void
 say_set_log_format(enum say_format format);
 
+/** \endcond ffi */
+
 /**
  * Return say format by name.
  *
@@ -246,12 +265,16 @@ say_set_log_format(enum say_format format);
 enum say_format
 say_format_by_name(const char *format);
 
+/** \cond ffi */
+
 struct ev_loop;
 struct ev_signal;
 
 void
 say_logrotate(struct ev_loop *, struct ev_signal *, int /* revents */);
 
+/** \endcond ffi */
+
 /** Init default logger. */
 void
 say_logger_init(const char *init_str,
@@ -268,12 +291,15 @@ vsay(int level, const char *filename, int line, const char *error,
      const char *format, va_list ap);
 
 /** \cond public */
+/** \cond ffi */
 typedef void (*sayfunc_t)(int, const char *, int, const char *,
 		    const char *, ...);
 
 /** Internal function used to implement say() macros */
 CFORMAT(printf, 5, 0) extern sayfunc_t _say;
 
+/** \endcond ffi */
+
 /**
  * Format and print a message to Tarantool log file.
  *
diff --git a/src/lib/crypto/crypto.h b/src/lib/crypto/crypto.h
index 027a42735..97f4ed565 100644
--- a/src/lib/crypto/crypto.h
+++ b/src/lib/crypto/crypto.h
@@ -53,6 +53,8 @@ extern "C" {
  * without encryption.
  */
 
+/** \cond ffi */
+
 enum crypto_algo {
 	/** None to disable encryption. */
 	CRYPTO_ALGO_NONE,
@@ -78,8 +80,12 @@ enum crypto_algo {
 	crypto_algo_MAX,
 };
 
+/** \endcond ffi */
+
 extern const char *crypto_algo_strs[];
 
+/** \cond ffi */
+
 enum crypto_mode {
 	/**
 	 * Electronic CodeBook. The message is split into blocks,
@@ -128,6 +134,8 @@ enum crypto_mode {
 	crypto_mode_MAX,
 };
 
+/** \endcond ffi */
+
 extern const char *crypto_mode_strs[];
 
 /**
@@ -151,6 +159,8 @@ enum {
 	CRYPTO_MAX_BLOCK_SIZE = 16,
 };
 
+/** \cond ffi */
+
 /**
  * OpenSSL API provides generic methods to do both encryption and
  * decryption depending on one 'int' parameter passed into
@@ -162,6 +172,8 @@ enum crypto_direction {
 	CRYPTO_DIR_ENCRYPT = 1,
 };
 
+/** \cond ffi */
+
 struct crypto_stream;
 
 /**
@@ -206,6 +218,8 @@ crypto_stream_commit(struct crypto_stream *s, char *out, int out_size);
 void
 crypto_stream_delete(struct crypto_stream *s);
 
+/** \endcond ffi */
+
 struct crypto_codec;
 
 /**
diff --git a/src/lib/csv/csv.h b/src/lib/csv/csv.h
index fb5a111d1..3c5c9e87e 100644
--- a/src/lib/csv/csv.h
+++ b/src/lib/csv/csv.h
@@ -36,6 +36,8 @@
 extern "C" {
 #endif
 
+/** \cond ffi */
+
 typedef void (*csv_emit_row_t)(void *ctx);
 typedef void (*csv_emit_field_t)(void *ctx, const char *field, const char *end);
 
@@ -59,6 +61,8 @@ struct csv
 	size_t buf_len;
 };
 
+/** \endcond ffi */
+
 enum csv_parser_option {
 	CSV_OPT_DELIMITER,
 	CSV_OPT_QUOTE,
@@ -68,6 +72,8 @@ enum csv_parser_option {
 	CSV_OPT_EMIT_CTX
 };
 
+/** \cond ffi */
+
 enum csv_iteraion_state {
 	CSV_IT_OK,
 	CSV_IT_EOL,
@@ -76,6 +82,8 @@ enum csv_iteraion_state {
 	CSV_IT_ERROR
 };
 
+/** \endcond ffi */
+
 enum csv_parser_state {
 	CSV_LEADING_SPACES,
 	CSV_OUT_OF_QUOTES,
@@ -93,6 +101,8 @@ enum csv_error_status {
 	CSV_ER_MEMORY_ERROR
 };
 
+/** \cond ffi */
+
 void
 csv_create(struct csv *csv);
 
@@ -105,6 +115,8 @@ csv_destroy(struct csv *csv);
 void
 csv_setopt(struct csv *csv, int opt, ...);
 
+/** \endcond ffi */
+
 /**
  * Parse input and call emit_row/emit_line.
  * Save tail to inside buffer,
@@ -125,6 +137,8 @@ csv_finish_parsing(struct csv *csv);
 int
 csv_get_error_status(struct csv *csv);
 
+/** \cond ffi */
+
 /**
  * @brief The csv_iterator struct allows iterate field by field through csv
  */
@@ -164,6 +178,8 @@ csv_feed(struct csv_iterator *it, const char *buf, size_t buf_len);
 size_t
 csv_escape_field(struct csv *csv, const char *field, size_t field_len, char *dst, size_t dst_size);
 
+/** \endcond ffi */
+
 
 static inline const char *
 csv_iterator_get_field(struct csv_iterator *it)
diff --git a/src/lib/salad/guava.h b/src/lib/salad/guava.h
index 9ed93d641..f9facc8d4 100644
--- a/src/lib/salad/guava.h
+++ b/src/lib/salad/guava.h
@@ -38,9 +38,13 @@
 extern "C" {
 #endif
 
+/** \cond ffi */
+
 int32_t
 guava(int64_t state, int32_t buckets);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern C */
 #endif
diff --git a/src/lib/swim/swim.h b/src/lib/swim/swim.h
index 4565eb976..12376cecc 100644
--- a/src/lib/swim/swim.h
+++ b/src/lib/swim/swim.h
@@ -39,6 +39,8 @@
 extern "C" {
 #endif
 
+/** \cond ffi */
+
 struct swim;
 struct rlist;
 struct tt_uuid;
@@ -62,6 +64,8 @@ enum swim_gc_mode {
 	SWIM_GC_ON = 1,
 };
 
+/** \endcond ffi */
+
 /**
  * Create a new SWIM instance. Do not bind to a port or set any
  * parameters. Allocation and initialization only. The function
@@ -70,6 +74,8 @@ enum swim_gc_mode {
 struct swim *
 swim_new(uint64_t generation);
 
+/** \cond ffi */
+
 /** Check if a swim instance is configured. */
 bool
 swim_is_configured(const struct swim *swim);
@@ -124,6 +130,8 @@ int
 swim_set_codec(struct swim *swim, enum crypto_algo algo, enum crypto_mode mode,
 	       const char *key, int key_size);
 
+/** \endcond ffi */
+
 /**
  * Stop listening and broadcasting messages, cleanup all internal
  * structures, free memory. The function yields. Actual deletion
@@ -140,6 +148,8 @@ swim_delete(struct swim *swim);
 int
 swim_fd(const struct swim *swim);
 
+/** \cond ffi */
+
 /** Add a new member. */
 int
 swim_add_member(struct swim *swim, const char *uri, const struct tt_uuid *uuid);
@@ -292,6 +302,8 @@ enum swim_ev_mask {
 	SWIM_EV_DROP            = 0b01000000,
 };
 
+/** \endcond ffi */
+
 /** On member event trigger context. */
 struct swim_on_member_event_ctx {
 	/** New, dropped, or updated member. */
diff --git a/src/lib/swim/swim_constants.h b/src/lib/swim/swim_constants.h
index cee109c8c..e088549bc 100644
--- a/src/lib/swim/swim_constants.h
+++ b/src/lib/swim/swim_constants.h
@@ -34,6 +34,8 @@
  * Constants for public API.
  */
 
+/** \cond ffi */
+
 enum swim_member_status {
 	/** The instance is ok, responds to requests. */
 	MEMBER_ALIVE = 0,
@@ -53,8 +55,12 @@ enum swim_member_status {
 	swim_member_status_MAX,
 };
 
+/** \endcond ffi */
+
 extern const char *swim_member_status_strs[];
 
+/** \cond ffi */
+
 /**
  * A monotonically growing value to refute false gossips and
  * update member attributes on remote instances. Any piece of
@@ -76,6 +82,8 @@ struct swim_incarnation {
 	uint64_t version;
 };
 
+/** \endcond ffi */
+
 /** Create a new incarnation value. */
 static inline void
 swim_incarnation_create(struct swim_incarnation *i, uint64_t generation,
diff --git a/src/lib/uri/uri.h b/src/lib/uri/uri.h
index b74c467f9..b716efd2f 100644
--- a/src/lib/uri/uri.h
+++ b/src/lib/uri/uri.h
@@ -40,6 +40,8 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 struct uri {
 	const char *scheme;
 	size_t scheme_len;
@@ -60,16 +62,22 @@ struct uri {
 	int host_hint;
 };
 
+/** \endcond ffi */
+
 #define URI_HOST_UNIX "unix/"
 #define URI_MAXHOST NI_MAXHOST
 #define URI_MAXSERVICE _POSIX_PATH_MAX /* _POSIX_PATH_MAX always > NI_MAXSERV */
 
+/** \cond ffi */
+
 int
 uri_parse(struct uri *uri, const char *str);
 
 int
 uri_format(char *str, int len, const struct uri *uri, bool write_password);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/lib/uuid/tt_uuid.h b/src/lib/uuid/tt_uuid.h
index 48cd68e69..6605d5cb3 100644
--- a/src/lib/uuid/tt_uuid.h
+++ b/src/lib/uuid/tt_uuid.h
@@ -43,6 +43,8 @@ extern "C" {
 
 enum { UUID_LEN = 16, UUID_STR_LEN = 36 };
 
+/** \cond ffi */
+
 /**
  * \brief UUID structure struct
  */
@@ -62,6 +64,8 @@ struct tt_uuid {
 void
 tt_uuid_create(struct tt_uuid *uu);
 
+/** \endcond ffi */
+
 /**
  * \brief Parse UUID from string.
  * \param in string
@@ -171,11 +175,15 @@ tt_uuid_is_equal(const struct tt_uuid *lhs, const struct tt_uuid *rhs)
 	return lp[0] == rp[0] && lp[1] == rp[1];
 }
 
+/** \cond ffi */
+
 extern const struct tt_uuid uuid_nil;
 
 char *
 tt_uuid_str(const struct tt_uuid *uu);
 
+/** \endcond ffi */
+
 int
 tt_uuid_from_strl(const char *in, size_t len, struct tt_uuid *uu);
 
diff --git a/src/lua/buffer.lua b/src/lua/buffer.lua
index ef0118c7c..41ff5bd5c 100644
--- a/src/lua/buffer.lua
+++ b/src/lua/buffer.lua
@@ -3,69 +3,6 @@
 local ffi = require('ffi')
 local READAHEAD = 16320
 
-ffi.cdef[[
-struct slab_cache;
-struct slab_cache *
-tarantool_lua_slab_cache();
-extern struct ibuf *tarantool_lua_ibuf;
-
-struct ibuf
-{
-    struct slab_cache *slabc;
-    char *buf;
-    /** Start of input. */
-    char *rpos;
-    /** End of useful input */
-    char *wpos;
-    /** End of ibuf. */
-    char *epos;
-    size_t start_capacity;
-};
-
-void
-ibuf_create(struct ibuf *ibuf, struct slab_cache *slabc, size_t start_capacity);
-
-void
-ibuf_destroy(struct ibuf *ibuf);
-
-void
-ibuf_reinit(struct ibuf *ibuf);
-
-void *
-ibuf_reserve_slow(struct ibuf *ibuf, size_t size);
-
-void *
-lua_static_aligned_alloc(size_t size, size_t alignment);
-
-/**
- * Register is a buffer to use with FFI functions, which usually
- * operate with pointers to scalar values like int, char, size_t,
- * void *. To avoid doing 'ffi.new(<type>[1])' on each such FFI
- * function invocation, a module can use one of attributes of the
- * register union.
- *
- * Naming policy of the attributes is easy to remember:
- * 'a' for array type + type name first letters + 'p' for pointer.
- *
- * For example:
- * - int[1] - <a>rray of <i>nt - ai;
- * - const unsigned char *[1] -
- *       <a>rray of <c>onst <u>nsigned <c>har <p> pointer - acucp.
- */
-union c_register {
-    size_t as[1];
-    void *ap[1];
-    int ai[1];
-    char ac[1];
-    const unsigned char *acucp[1];
-    unsigned long aul[1];
-    uint16_t u16;
-    uint32_t u32;
-    uint64_t u64;
-    int64_t i64;
-};
-]]
-
 local builtin = ffi.C
 local ibuf_t = ffi.typeof('struct ibuf')
 
diff --git a/src/lua/clock.lua b/src/lua/clock.lua
index 60c78663c..176ac8612 100644
--- a/src/lua/clock.lua
+++ b/src/lua/clock.lua
@@ -2,17 +2,6 @@
 local clock = {}
 local ffi = require('ffi')
 
-ffi.cdef[[
-    double clock_realtime(void);
-    double clock_monotonic(void);
-    double clock_process(void);
-    double clock_thread(void);
-    uint64_t clock_realtime64(void);
-    uint64_t clock_monotonic64(void);
-    uint64_t clock_process64(void);
-    uint64_t clock_thread64(void);
-]]
-
 local C = ffi.C
 
 clock.realtime = C.clock_realtime
diff --git a/src/lua/crypto.lua b/src/lua/crypto.lua
index bf3064c70..226d53061 100644
--- a/src/lua/crypto.lua
+++ b/src/lua/crypto.lua
@@ -4,72 +4,6 @@ local ffi = require('ffi')
 local buffer = require('buffer')
 local reg = buffer.reg1
 
-ffi.cdef[[
-    /* from openssl/err.h */
-    unsigned long ERR_get_error(void);
-    char *ERR_error_string(unsigned long e, char *buf);
-
-    /* from openssl/evp.h */
-    typedef void ENGINE;
-
-    typedef struct {} EVP_MD_CTX;
-    typedef struct {} EVP_MD;
-    EVP_MD_CTX *crypto_EVP_MD_CTX_new(void);
-    void crypto_EVP_MD_CTX_free(EVP_MD_CTX *ctx);
-    int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
-    int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
-    int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
-    const EVP_MD *EVP_get_digestbyname(const char *name);
-
-    typedef struct {} HMAC_CTX;
-    HMAC_CTX *crypto_HMAC_CTX_new(void);
-    void crypto_HMAC_CTX_free(HMAC_CTX *ctx);
-    int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
-                 const EVP_MD *md, ENGINE *impl);
-    int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
-    int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
-
-    enum crypto_algo {
-        CRYPTO_ALGO_NONE,
-        CRYPTO_ALGO_AES128,
-        CRYPTO_ALGO_AES192,
-        CRYPTO_ALGO_AES256,
-        CRYPTO_ALGO_DES,
-    };
-
-    enum crypto_mode {
-        CRYPTO_MODE_ECB,
-        CRYPTO_MODE_CBC,
-        CRYPTO_MODE_CFB,
-        CRYPTO_MODE_OFB,
-    };
-
-    enum crypto_direction {
-        CRYPTO_DIR_DECRYPT = 0,
-        CRYPTO_DIR_ENCRYPT = 1,
-    };
-
-    struct crypto_stream;
-
-    struct crypto_stream *
-    crypto_stream_new(enum crypto_algo algo, enum crypto_mode mode,
-                      enum crypto_direction dir);
-
-    int
-    crypto_stream_begin(struct crypto_stream *s, const char *key, int key_size,
-                        const char *iv, int iv_size);
-
-    int
-    crypto_stream_append(struct crypto_stream *s, const char *in, int in_size,
-                         char *out, int out_size);
-
-    int
-    crypto_stream_commit(struct crypto_stream *s, char *out, int out_size);
-
-    void
-    crypto_stream_delete(struct crypto_stream *s);
-]]
-
 local function openssl_err_str()
   return ffi.string(ffi.C.ERR_error_string(ffi.C.ERR_get_error(), nil))
 end
diff --git a/src/lua/csv.lua b/src/lua/csv.lua
index 7dff2f213..569ae57ca 100644
--- a/src/lua/csv.lua
+++ b/src/lua/csv.lua
@@ -3,54 +3,6 @@
 local ffi = require('ffi')
 local log = require('log')
 
-ffi.cdef[[
-    typedef void (*csv_emit_row_t)(void *ctx);
-    typedef void (*csv_emit_field_t)(void *ctx, const char *field, const char *end);
-
-    struct csv
-    {
-        void *emit_ctx;
-        csv_emit_row_t emit_row;
-        csv_emit_field_t emit_field;
-        char delimiter;
-        char quote_char;
-
-        char prev_symbol;
-        int error_status;
-        int ending_spaces;
-
-        void *(*realloc)(void*, size_t);
-
-        int state;
-        char *buf;
-        char *bufp;
-        size_t buf_len;
-    };
-
-    void csv_create(struct csv *csv);
-    void csv_destroy(struct csv *csv);
-    void csv_setopt(struct csv *csv, int opt, ...);
-
-    struct csv_iterator {
-        struct csv *csv;
-        const char *buf_begin;
-        const char *buf_end;
-        const char *field;
-        size_t field_len;
-    };
-    void csv_iterator_create(struct csv_iterator *it, struct csv *csv);
-    int csv_next(struct csv_iterator *);
-    void csv_feed(struct csv_iterator *, const char *, size_t);
-    size_t csv_escape_field(struct csv *csv, const char *field, size_t field_len, char *dst, size_t buf_size);
-    enum {
-        CSV_IT_OK,
-        CSV_IT_EOL,
-        CSV_IT_NEEDMORE,
-        CSV_IT_EOF,
-        CSV_IT_ERROR
-    };
-]]
-
 local iter = function(csvstate, i)
     local readable = csvstate[1]
     local csv_chunk_size = csvstate[2]
diff --git a/src/lua/digest.h b/src/lua/digest.h
index c10b087da..6fa4d9b24 100644
--- a/src/lua/digest.h
+++ b/src/lua/digest.h
@@ -37,9 +37,13 @@
 extern "C" {
 #endif
 
+/** \cond ffi */
+
 unsigned char *
 SHA1internal(const unsigned char *d, size_t n, unsigned char *md);
 
+/** \endcond ffi */
+
 struct lua_State;
 
 void
diff --git a/src/lua/digest.lua b/src/lua/digest.lua
index 6ed91cfa2..fddb6ab32 100644
--- a/src/lua/digest.lua
+++ b/src/lua/digest.lua
@@ -5,32 +5,6 @@ local crypto = require('crypto')
 local bit = require('bit')
 local static_alloc = require('buffer').static_alloc
 
-ffi.cdef[[
-    /* internal implementation */
-    unsigned char *SHA1internal(const unsigned char *d, size_t n, unsigned char *md);
-
-    /* from libc */
-    int snprintf(char *str, size_t size, const char *format, ...);
-
-    typedef uint32_t (*crc32_func)(uint32_t crc,
-        const unsigned char *buf, unsigned int len);
-    extern int32_t guava(int64_t state, int32_t buckets);
-    extern crc32_func crc32_calc;
-
-    /* base64 */
-    int base64_bufsize(int binsize, int options);
-    int base64_decode(const char *in_base64, int in_len, char *out_bin, int out_len);
-    int base64_encode(const char *in_bin, int in_len, char *out_base64, int out_len, int options);
-
-    /* random */
-    void random_bytes(char *, size_t);
-
-    /* from third_party/PMurHash.h */
-    void PMurHash32_Process(uint32_t *ph1, uint32_t *pcarry, const void *key, int len);
-    uint32_t PMurHash32_Result(uint32_t h1, uint32_t carry, uint32_t total_length);
-    uint32_t PMurHash32(uint32_t seed, const void *key, int len);
-]]
-
 -- @sa base64.h
 local BASE64_NOPAD = 1
 local BASE64_NOWRAP = 2
diff --git a/src/lua/env.lua b/src/lua/env.lua
index b150a48a9..cf6fcf4ee 100644
--- a/src/lua/env.lua
+++ b/src/lua/env.lua
@@ -2,13 +2,6 @@ local ffi = require('ffi')
 local os = require('os')
 local errno = require('errno')
 
-ffi.cdef[[
-    extern char **environ;
-
-    int   setenv(const char *name, const char *value, int overwrite);
-    int   unsetenv(const char *name);
-]]
-
 local environ = ffi.C.environ
 
 os.environ = function()
diff --git a/src/lua/errno.lua b/src/lua/errno.lua
index db800ce30..c80e9cbe6 100644
--- a/src/lua/errno.lua
+++ b/src/lua/errno.lua
@@ -1,10 +1,6 @@
 local ffi = require('ffi')
 local errno_list = require('errno')
 
-ffi.cdef[[
-    char *strerror(int errnum);
-]]
-
 local function strerror(errno)
     if errno == nil then
         errno = ffi.errno()
diff --git a/src/lua/error.lua b/src/lua/error.lua
index d091ee48b..076f7bdd7 100644
--- a/src/lua/error.lua
+++ b/src/lua/error.lua
@@ -1,36 +1,6 @@
 -- error.lua (internal file)
 
 local ffi = require('ffi')
-ffi.cdef[[
-struct type_info;
-
-enum {
-    DIAG_ERRMSG_MAX = 512,
-    DIAG_FILENAME_MAX = 256
-};
-
-typedef void (*error_f)(struct error *e);
-
-struct error {
-    error_f _destroy;
-    error_f _raise;
-    error_f _log;
-    const struct type_info *_type;
-    int _refs;
-    int _saved_errno;
-    /** Line number. */
-    unsigned _line;
-    /* Source file name. */
-    char _file[DIAG_FILENAME_MAX];
-    /* Error description. */
-    char _errmsg[DIAG_ERRMSG_MAX];
-};
-
-char *
-exception_get_string(struct error *e, const struct method_info *method);
-int
-exception_get_int(struct error *e, const struct method_info *method);
-]]
 
 local REFLECTION_CACHE = {}
 
diff --git a/src/lua/fiber.lua b/src/lua/fiber.lua
index 8712ee0d6..113385fec 100644
--- a/src/lua/fiber.lua
+++ b/src/lua/fiber.lua
@@ -2,16 +2,6 @@
 
 local fiber = require('fiber')
 local ffi = require('ffi')
-ffi.cdef[[
-double
-fiber_time(void);
-uint64_t
-fiber_time64(void);
-double
-fiber_clock(void);
-uint64_t
-fiber_clock64(void);
-]]
 local C = ffi.C
 
 local function fiber_time()
diff --git a/src/lua/fio.lua b/src/lua/fio.lua
index cb224f3d0..696ba3a29 100644
--- a/src/lua/fio.lua
+++ b/src/lua/fio.lua
@@ -6,12 +6,6 @@ local buffer = require('buffer')
 local fiber = require('fiber')
 local errno = require('errno')
 
-ffi.cdef[[
-    int umask(int mask);
-    char *dirname(char *path);
-    int chdir(const char *path);
-]]
-
 local const_char_ptr_t = ffi.typeof('const char *')
 
 local internal = fio.internal
diff --git a/src/lua/iconv.lua b/src/lua/iconv.lua
index ade66d760..019b78bc2 100644
--- a/src/lua/iconv.lua
+++ b/src/lua/iconv.lua
@@ -2,14 +2,6 @@ local ffi    = require('ffi')
 local errno  = require('errno')
 local buffer = require('buffer')
 
-ffi.cdef[[
-typedef struct iconv *iconv_t;
-iconv_t tnt_iconv_open(const char *tocode, const char *fromcode);
-void    tnt_iconv_close(iconv_t cd);
-size_t  tnt_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
-                   char **outbuf, size_t *outbytesleft);
-]]
-
 local iconv_t         = ffi.typeof('struct iconv')
 local char_ptr_arr_t  = ffi.typeof('char *[1]')
 local cchar_ptr_arr_t = ffi.typeof('const char *[1]')
diff --git a/src/lua/init.c b/src/lua/init.c
index 097dd8495..8eb9c67a5 100644
--- a/src/lua/init.c
+++ b/src/lua/init.c
@@ -81,6 +81,7 @@ bool start_loop = true;
 
 /* contents of src/lua/ files */
 extern char strict_lua[],
+    load_ffi_defs_lua[],
 	uuid_lua[],
 	msgpackffi_lua[],
 	fun_lua[],
@@ -124,6 +125,7 @@ extern char strict_lua[],
 
 static const char *lua_modules[] = {
 	/* Make it first to affect load of all other modules */
+    "load_ffi_defs", load_ffi_defs_lua,
 	"strict", strict_lua,
 	"fun", fun_lua,
 	"debug", debug_lua,
diff --git a/src/lua/init.h b/src/lua/init.h
index 507360738..197831130 100644
--- a/src/lua/init.h
+++ b/src/lua/init.h
@@ -77,9 +77,13 @@ tarantool_lua_run_script(char *path, bool force_interactive,
 
 extern char *history;
 
+/** \cond ffi */
+
 struct slab_cache *
 tarantool_lua_slab_cache();
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/lua/init.lua b/src/lua/init.lua
index ff3e74c3c..1ee8ae414 100644
--- a/src/lua/init.lua
+++ b/src/lua/init.lua
@@ -2,46 +2,6 @@
 -- init.lua -- internal file
 
 local ffi = require('ffi')
-ffi.cdef[[
-struct type_info;
-struct method_info;
-
-enum ctype {
-    CTYPE_VOID = 0,
-    CTYPE_INT,
-    CTYPE_CONST_CHAR_PTR
-};
-
-struct type_info {
-    const char *name;
-    const struct type_info *parent;
-    const struct method_info *methods;
-};
-
-enum { METHOD_ARG_MAX = 8 };
-
-struct method_info {
-    const struct type_info *owner;
-    const char *name;
-    enum ctype rtype;
-    enum ctype atype[METHOD_ARG_MAX];
-    int nargs;
-    bool isconst;
-
-    union {
-        /* Add extra space to get proper struct size in C */
-        void *_spacer[2];
-    };
-};
-
-double
-tarantool_uptime(void);
-typedef int32_t pid_t;
-pid_t getpid(void);
-void
-tarantool_exit(int);
-]]
-
 local fio = require("fio")
 
 local soext = (jit.os == "OSX" and "dylib" or "so")
diff --git a/src/lua/load_ffi_defs.footer.lua b/src/lua/load_ffi_defs.footer.lua
new file mode 100644
index 000000000..f92065122
--- /dev/null
+++ b/src/lua/load_ffi_defs.footer.lua
@@ -0,0 +1,155 @@
+
+]]
+
+-- {{{ Definitions
+
+-- POSIX demands to have five fields in struct group:
+-- char    *pw_name   User's login name.
+-- uid_t    pw_uid    Numerical user ID.
+-- gid_t    pw_gid    Numerical group ID.
+-- char    *pw_dir    Initial working directory.
+-- char    *pw_shell  Program to use as shell.
+--
+-- So we'll extract only them.
+if ffi.os == 'OSX' or ffi.os == 'BSD' then
+    ffi.cdef[[
+        struct passwd {
+            char    *pw_name;    /* user name */
+            char    *pw_passwd;  /* encrypted password */
+            uid_t    pw_uid;     /* user uid */
+            gid_t    pw_gid;     /* user gid */
+            time_t   pw_change;  /* password change time */
+            char    *pw_class;   /* user access class */
+            char    *pw_gecos;   /* Honeywell login info */
+            char    *pw_dir;     /* home directory */
+            char    *pw_shell;   /* default shell */
+            time_t   pw_expire;  /* account expiration */
+            int      pw_fields;  /* internal: fields filled in */
+        };
+    ]]
+else
+    ffi.cdef[[
+        struct passwd {
+            char *pw_name;   /* username */
+            char *pw_passwd; /* user password */
+            int   pw_uid;    /* user ID */
+            int   pw_gid;    /* group ID */
+            char *pw_gecos;  /* user information */
+            char *pw_dir;    /* home directory */
+            char *pw_shell;  /* shell program */
+        };
+    ]]
+end
+
+-- }}}
+
+ffi.cdef[[
+    /* From src/lib/core/diag.h
+     * This struct is here because src/lua/error.lua
+     * uses underscored member names
+     * (i.e. we cannot use 'type' member since it's a keyword)
+     */
+    struct error {
+        error_f _destroy;
+        error_f _raise;
+        error_f _log;
+        const struct type_info *_type;
+        int _refs;
+        int _saved_errno;
+        /** Line number. */
+        unsigned _line;
+        /* Source file name. */
+        char _file[DIAG_FILENAME_MAX];
+        /* Error description. */
+        char _errmsg[DIAG_ERRMSG_MAX];
+    };
+
+    /* From src/box/user_def.h
+     * This enum is here because Lua C parser
+     * incorrecly assigns PRIV_ALL = -1
+     * - this is signed type, and unsigned is required
+     */
+    enum priv_type {
+        /* SELECT */
+        PRIV_R = 1,
+        /* INSERT, UPDATE, UPSERT, DELETE, REPLACE */
+        PRIV_W = 2,
+        /* CALL */
+        PRIV_X = 4,
+        /* SESSION */
+        PRIV_S = 8,
+        /* USAGE */
+        PRIV_U = 16,
+        /* CREATE */
+        PRIV_C = 32,
+        /* DROP */
+        PRIV_D = 64,
+        /* ALTER */
+        PRIV_A = 128,
+        /* REFERENCE - required by ANSI - not implemented */
+        PRIV_REFERENCE = 256,
+        /* TRIGGER - required by ANSI - not implemented */
+        PRIV_TRIGGER = 512,
+        /* INSERT - required by ANSI - not implemented */
+        PRIV_INSERT = 1024,
+        /* UPDATE - required by ANSI - not implemented */
+        PRIV_UPDATE = 2048,
+        /* DELETE - required by ANSI - not implemented */
+        PRIV_DELETE = 4096,
+        /* This is never granted, but used internally. */
+        PRIV_GRANT = 8192,
+        /* Never granted, but used internally. */
+        PRIV_REVOKE = 16384,
+        /* all bits */
+        PRIV_ALL  = 4294967295
+    };
+]]
+
+ffi.cdef[[
+    /* From src/lib/small/ibuf.h (submodule) */
+
+    struct ibuf
+    {
+        struct slab_cache *slabc;
+        char *buf;
+        /** Start of input. */
+        char *rpos;
+        /** End of useful input */
+        char *wpos;
+        /** End of ibuf. */
+        char *epos;
+        size_t start_capacity;
+    };
+
+    void
+    ibuf_create(struct ibuf *ibuf, struct slab_cache *slabc, size_t start_capacity);
+
+    void
+    ibuf_destroy(struct ibuf *ibuf);
+
+    void
+    ibuf_reinit(struct ibuf *ibuf);
+
+    void *
+    ibuf_reserve_slow(struct ibuf *ibuf, size_t size);
+]]
+
+ffi.cdef[[
+    /* From src/lib/msgpuck/msgpuck.h (submodule) */
+
+    uint32_t
+    mp_decode_extl(const char **data, int8_t *type);
+
+    char *
+    mp_encode_float(char *data, float num);
+
+    char *
+    mp_encode_double(char *data, double num);
+
+    float
+    mp_decode_float(const char **data);
+
+    double
+    mp_decode_double(const char **data);
+]]
+
diff --git a/src/lua/load_ffi_defs.header.lua b/src/lua/load_ffi_defs.header.lua
new file mode 100755
index 000000000..da88d5b25
--- /dev/null
+++ b/src/lua/load_ffi_defs.header.lua
@@ -0,0 +1,187 @@
+---
+--- Unified Lua ffi.cdef builder header file.
+--- The definitions below are either from system headers
+--- or from dependent packages or tarantol repo files
+--- which cannot be automatically preprocessed.
+---
+
+ffi = require('ffi')
+
+ffi.cdef[[
+/* from libc */
+
+char *strerror(int errnum);
+int snprintf(char *str, size_t size, const char *format, ...);
+const char *memmem(const char *haystack, size_t haystack_len,
+                   const char *needle, size_t needle_len);
+int memcmp(const char *mem1, const char *mem2, size_t num);
+int isspace(int c);
+typedef int32_t pid_t;
+pid_t getpid(void);
+
+// GID_T, UID_T and TIME_T are, essentially, `integer types`.
+// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
+typedef int uid_t;
+typedef int gid_t;
+typedef long time_t;
+
+// POSIX demands to have three fields in struct group:
+// http://pubs.opengroup.org/onlinepubs/009695399/basedefs/grp.h.html
+// char   *gr_name The name of the group.
+// gid_t   gr_gid  Numerical group ID.
+// char  **gr_mem  Pointer to a null-terminated array of character pointers to
+//                 member names.
+//
+// So we'll extract only them.
+struct group {
+    char    *gr_name;    /* group name */
+    char    *gr_passwd;  /* group password */
+    gid_t    gr_gid;     /* group id */
+    char   **gr_mem;     /* group members */
+};
+
+uid_t          getuid();
+struct passwd *getpwuid(uid_t uid);
+struct passwd *getpwnam(const char *login);
+void           endpwent();
+struct passwd *getpwent();
+void           setpwent();
+gid_t          getgid();
+struct group  *getgrgid(gid_t gid);
+struct group  *getgrnam(const char *group);
+struct group  *getgrent();
+void           endgrent();
+void           setgrent();
+
+int umask(int mask);
+char *dirname(char *path);
+int chdir(const char *path);
+
+struct gc_socket {
+    const int fd;
+};
+
+typedef uint32_t socklen_t;
+typedef ptrdiff_t ssize_t;
+struct sockaddr;
+
+int connect(int sockfd, const struct sockaddr *addr,
+            socklen_t addrlen);
+int bind(int sockfd, const struct sockaddr *addr,
+         socklen_t addrlen);
+ssize_t write(int fd, const char *octets, size_t len);
+ssize_t read(int fd, void *buf, size_t count);
+int listen(int fd, int backlog);
+int socket(int domain, int type, int protocol);
+int shutdown(int s, int how);
+ssize_t send(int sockfd, const void *buf, size_t len, int flags);
+ssize_t recv(int s, void *buf, size_t len, int flags);
+int accept(int s, void *addr, void *addrlen);
+ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
+               const struct sockaddr *dest_addr, socklen_t addrlen);
+int setsockopt(int s, int level, int iname, const void *opt, size_t optlen);
+int getsockopt(int s, int level, int iname, void *ptr, size_t *optlen);
+
+typedef struct { int active; int timeout; } linger_t;
+
+struct protoent {
+    char  *p_name;       /* official protocol name */
+    char **p_aliases;    /* alias list */
+    int    p_proto;      /* protocol number */
+};
+struct protoent *getprotobyname(const char *name);
+
+extern char **environ;
+int setenv(const char *name, const char *value, int overwrite);
+int unsetenv(const char *name);
+
+/* from third_party/base64.h */
+int base64_bufsize(int binsize, int options);
+int base64_decode(const char *in_base64, int in_len, char *out_bin, int out_len);
+int base64_encode(const char *in_bin, int in_len, char *out_base64, int out_len, int options);
+
+/* from third_party/PMurHash.h */
+void PMurHash32_Process(uint32_t *ph1, uint32_t *pcarry, const void *key, int len);
+uint32_t PMurHash32_Result(uint32_t h1, uint32_t carry, uint32_t total_length);
+uint32_t PMurHash32(uint32_t seed, const void *key, int len);
+
+/* from <iconv.h> */
+typedef struct iconv *iconv_t;
+
+/* from src/lua/tnt_iconv.c */
+iconv_t tnt_iconv_open(const char *tocode, const char *fromcode);
+void    tnt_iconv_close(iconv_t cd);
+size_t  tnt_iconv(iconv_t cd, const char **inbuf, size_t *inbytesleft,
+                  char **outbuf, size_t *outbytesleft);
+
+/* from openssl/engine.h */
+typedef void ENGINE;
+
+/* from openssl/err.h */
+unsigned long ERR_get_error(void);
+char *ERR_error_string(unsigned long e, char *buf);
+
+/* from openssl/evp.h */
+typedef struct {} EVP_MD_CTX;
+typedef struct {} EVP_MD;
+int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
+int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
+int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s);
+const EVP_MD *EVP_get_digestbyname(const char *name);
+
+/* from openssl/hmac.h */
+typedef struct {} HMAC_CTX;
+int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
+                 const EVP_MD *md, ENGINE *impl);
+int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len);
+int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
+
+/* from src/lib/crypto/crypto.c */
+EVP_MD_CTX *crypto_EVP_MD_CTX_new(void);
+void crypto_EVP_MD_CTX_free(EVP_MD_CTX *ctx);
+HMAC_CTX *crypto_HMAC_CTX_new(void);
+void crypto_HMAC_CTX_free(HMAC_CTX *ctx);
+
+/* from src/lib/uuid/tt_uuid.h (inline functions) */
+struct tt_uuid;
+int tt_uuid_from_string(const char *in, struct tt_uuid *uu);
+void tt_uuid_to_string(const struct tt_uuid *uu, char *out);
+void tt_uuid_bswap(struct tt_uuid *uu);
+bool tt_uuid_is_nil(const struct tt_uuid *uu);
+bool tt_uuid_is_equal(const struct tt_uuid *lhs, const struct tt_uuid *rhs);
+
+/* from src/lua/init.h (declaration of tarantool_lua_slab_cache) */
+struct slab_cache;
+
+/* from src/lua/buffer.c */
+void *lua_static_aligned_alloc(size_t size, size_t alignment);
+
+/* from src/lua/buffer.lua */
+
+/**
+ * Register is a buffer to use with FFI functions, which usually
+ * operate with pointers to scalar values like int, char, size_t,
+ * void *. To avoid doing 'ffi.new(<type>[1])' on each such FFI
+ * function invocation, a module can use one of attributes of the
+ * register union.
+ *
+ * Naming policy of the attributes is easy to remember:
+ * 'a' for array type + type name first letters + 'p' for pointer.
+ *
+ * For example:
+ * - int[1] - <a>rray of <i>nt - ai;
+ * - const unsigned char *[1] -
+ *       <a>rray of <c>onst <u>nsigned <c>har <p> pointer - acucp.
+ */
+union c_register {
+    size_t as[1];
+    void *ap[1];
+    int ai[1];
+    char ac[1];
+    const unsigned char *acucp[1];
+    unsigned long aul[1];
+    uint16_t u16;
+    uint32_t u32;
+    uint64_t u64;
+    int64_t i64;
+};
diff --git a/src/lua/log.lua b/src/lua/log.lua
index 312c14d5e..4657463de 100644
--- a/src/lua/log.lua
+++ b/src/lua/log.lua
@@ -1,54 +1,6 @@
 -- log.lua
 --
 local ffi = require('ffi')
-ffi.cdef[[
-    typedef void (*sayfunc_t)(int level, const char *filename, int line,
-               const char *error, const char *format, ...);
-
-    enum say_logger_type {
-        SAY_LOGGER_BOOT,
-        SAY_LOGGER_STDERR,
-        SAY_LOGGER_FILE,
-        SAY_LOGGER_PIPE,
-        SAY_LOGGER_SYSLOG
-    };
-
-    enum say_logger_type
-    log_type();
-
-    void
-    say_set_log_level(int new_level);
-
-    void
-    say_set_log_format(enum say_format format);
-
-
-    extern sayfunc_t _say;
-    extern struct ev_loop;
-    extern struct ev_signal;
-
-    extern void
-    say_logrotate(struct ev_loop *, struct ev_signal *, int);
-
-    enum say_level {
-        S_FATAL,
-        S_SYSERROR,
-        S_ERROR,
-        S_CRIT,
-        S_WARN,
-        S_INFO,
-        S_VERBOSE,
-        S_DEBUG
-    };
-
-    enum say_format {
-        SF_PLAIN,
-        SF_JSON
-    };
-    pid_t log_pid;
-    extern int log_level;
-    extern int log_format;
-]]
 
 local S_WARN = ffi.C.S_WARN
 local S_INFO = ffi.C.S_INFO
diff --git a/src/lua/msgpackffi.lua b/src/lua/msgpackffi.lua
index 5331dc75f..e5437cdf1 100644
--- a/src/lua/msgpackffi.lua
+++ b/src/lua/msgpackffi.lua
@@ -11,25 +11,6 @@ local uint32_ptr_t = ffi.typeof('uint32_t *')
 local uint64_ptr_t = ffi.typeof('uint64_t *')
 local const_char_ptr_t = ffi.typeof('const char *')
 
-ffi.cdef([[
-char *
-mp_encode_float(char *data, float num);
-char *
-mp_encode_double(char *data, double num);
-char *
-mp_encode_decimal(char *data, decimal_t *dec);
-uint32_t
-mp_sizeof_decimal(const decimal_t *dec);
-float
-mp_decode_float(const char **data);
-double
-mp_decode_double(const char **data);
-uint32_t
-mp_decode_extl(const char **data, int8_t *type);
-decimal_t *
-decimal_unpack(const char **data, uint32_t len, decimal_t *dec);
-]])
-
 local strict_alignment = (jit.arch == 'arm')
 local reg = buffer.reg1
 
diff --git a/src/lua/pwd.lua b/src/lua/pwd.lua
index d59594b46..8dbd3e914 100644
--- a/src/lua/pwd.lua
+++ b/src/lua/pwd.lua
@@ -1,89 +1,6 @@
 local ffi   = require('ffi')
 local errno = require('errno')
 
--- {{{ Definitions
-
--- GID_T, UID_T and TIME_T are, essentially, `integer types`.
--- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html
-ffi.cdef[[
-    typedef int uid_t;
-    typedef int gid_t;
-    typedef long time_t;
-]]
-
--- POSIX demands to have three fields in struct group:
--- http://pubs.opengroup.org/onlinepubs/009695399/basedefs/grp.h.html
--- char   *gr_name The name of the group.
--- gid_t   gr_gid  Numerical group ID.
--- char  **gr_mem  Pointer to a null-terminated array of character pointers to
---                 member names.
---
--- So we'll extract only them.
-ffi.cdef[[
-    struct group {
-        char    *gr_name;    /* group name */
-        char    *gr_passwd;  /* group password */
-        gid_t    gr_gid;     /* group id */
-        char   **gr_mem;     /* group members */
-    };
-]]
-
--- POSIX demands to have five fields in struct group:
--- char    *pw_name   User's login name.
--- uid_t    pw_uid    Numerical user ID.
--- gid_t    pw_gid    Numerical group ID.
--- char    *pw_dir    Initial working directory.
--- char    *pw_shell  Program to use as shell.
---
--- So we'll extract only them.
-if ffi.os == 'OSX' or ffi.os == 'BSD' then
-    ffi.cdef[[
-        struct passwd {
-            char    *pw_name;    /* user name */
-            char    *pw_passwd;  /* encrypted password */
-            uid_t    pw_uid;     /* user uid */
-            gid_t    pw_gid;     /* user gid */
-            time_t   pw_change;  /* password change time */
-            char    *pw_class;   /* user access class */
-            char    *pw_gecos;   /* Honeywell login info */
-            char    *pw_dir;     /* home directory */
-            char    *pw_shell;   /* default shell */
-            time_t   pw_expire;  /* account expiration */
-            int      pw_fields;  /* internal: fields filled in */
-        };
-    ]]
-else
-    ffi.cdef[[
-        struct passwd {
-            char *pw_name;   /* username */
-            char *pw_passwd; /* user password */
-            int   pw_uid;    /* user ID */
-            int   pw_gid;    /* group ID */
-            char *pw_gecos;  /* user information */
-            char *pw_dir;    /* home directory */
-            char *pw_shell;  /* shell program */
-        };
-    ]]
-end
-
-ffi.cdef[[
-    uid_t          getuid();
-    struct passwd *getpwuid(uid_t uid);
-    struct passwd *getpwnam(const char *login);
-    void           endpwent();
-    struct passwd *getpwent();
-    void           setpwent();
-
-    gid_t          getgid();
-    struct group  *getgrgid(gid_t gid);
-    struct group  *getgrnam(const char *group);
-    struct group  *getgrent();
-    void           endgrent();
-    void           setgrent();
-]]
-
--- }}}
-
 -- {{{ Error handling
 
 local pwgr_errstr = "get%s failed [errno %d]: %s"
diff --git a/src/lua/socket.h b/src/lua/socket.h
index ec4e79d87..727765c67 100644
--- a/src/lua/socket.h
+++ b/src/lua/socket.h
@@ -40,12 +40,16 @@ extern "C" {
 struct lua_State;
 void tarantool_lua_socket_init(struct lua_State *L);
 
+/** \cond ffi */
+
 int
 lbox_socket_local_resolve(const char *host, const char *port,
 			  struct sockaddr *addr, socklen_t *socklen);
 int
 lbox_socket_nonblock(int fh, int mode);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif
diff --git a/src/lua/socket.lua b/src/lua/socket.lua
index a334ad45b..1c18e5983 100644
--- a/src/lua/socket.lua
+++ b/src/lua/socket.lua
@@ -16,51 +16,6 @@ local static_alloc = buffer.static_alloc
 
 local format = string.format
 
-ffi.cdef[[
-    struct gc_socket {
-        const int fd;
-    };
-    typedef uint32_t socklen_t;
-    typedef ptrdiff_t ssize_t;
-
-    int connect(int sockfd, const struct sockaddr *addr,
-                socklen_t addrlen);
-    int bind(int sockfd, const struct sockaddr *addr,
-                socklen_t addrlen);
-
-    ssize_t write(int fd, const char *octets, size_t len);
-    ssize_t read(int fd, void *buf, size_t count);
-    int listen(int fd, int backlog);
-    int socket(int domain, int type, int protocol);
-    int coio_close(int s);
-    int shutdown(int s, int how);
-    ssize_t send(int sockfd, const void *buf, size_t len, int flags);
-    ssize_t recv(int s, void *buf, size_t len, int flags);
-    int accept(int s, void *addr, void *addrlen);
-    ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
-                   const struct sockaddr *dest_addr, socklen_t addrlen);
-
-    int
-    lbox_socket_local_resolve(const char *host, const char *port,
-                         struct sockaddr *addr, socklen_t *socklen);
-    int lbox_socket_nonblock(int fd, int mode);
-
-    int setsockopt(int s, int level, int iname, const void *opt, size_t optlen);
-    int getsockopt(int s, int level, int iname, void *ptr, size_t *optlen);
-
-    typedef struct { int active; int timeout; } linger_t;
-
-    struct protoent {
-        char  *p_name;       /* official protocol name */
-        char **p_aliases;    /* alias list */
-        int    p_proto;      /* protocol number */
-    };
-    struct protoent *getprotobyname(const char *name);
-
-    void *memmem(const void *haystack, size_t haystacklen,
-        const void *needle, size_t needlelen);
-]]
-
 local gc_socket_t = ffi.metatype(ffi.typeof('struct gc_socket'), {
     __gc = function (socket)
         if socket.fd < 0 then return end
diff --git a/src/lua/string.h b/src/lua/string.h
index c40a851e0..fd390b093 100644
--- a/src/lua/string.h
+++ b/src/lua/string.h
@@ -39,11 +39,15 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 void
 string_strip_helper(const char *inp, size_t inp_len, const char *chars,
 		    size_t chars_len, bool lstrip, bool rstrip,
 		    size_t *newstart, size_t *newlen);
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif /* defined(__cplusplus) */
diff --git a/src/lua/string.lua b/src/lua/string.lua
index 6e12c59ae..74bc174c3 100644
--- a/src/lua/string.lua
+++ b/src/lua/string.lua
@@ -2,18 +2,6 @@ local ffi = require('ffi')
 local buffer = require('buffer')
 local static_alloc = buffer.static_alloc
 
-ffi.cdef[[
-    const char *
-    memmem(const char *haystack, size_t haystack_len,
-           const char *needle,   size_t needle_len);
-    int memcmp(const char *mem1, const char *mem2, size_t num);
-    int isspace(int c);
-    void
-    string_strip_helper(const char *inp, size_t inp_len, const char *chars,
-                        size_t chars_len, bool lstrip, bool rstrip,
-                        size_t *newstart, size_t *newlen);
-]]
-
 local c_char_ptr     = ffi.typeof('const char *')
 local strip_newstart = buffer.reg1.aul
 local strip_newlen   = buffer.reg2.aul
diff --git a/src/lua/swim.lua b/src/lua/swim.lua
index 01eeb7eae..18015a0c4 100644
--- a/src/lua/swim.lua
+++ b/src/lua/swim.lua
@@ -6,119 +6,6 @@ local crypto = require('crypto')
 local fiber = require('fiber')
 local internal = require('swim')
 
-ffi.cdef[[
-    struct swim;
-    struct tt_uuid;
-    struct swim_iterator;
-    struct swim_member;
-
-    enum swim_gc_mode {
-        SWIM_GC_DEFAULT = -1,
-        SWIM_GC_OFF = 0,
-        SWIM_GC_ON = 1,
-    };
-
-    enum swim_member_status {
-        MEMBER_ALIVE = 0,
-        MEMBER_SUSPECTED,
-        MEMBER_DEAD,
-        MEMBER_LEFT,
-    };
-
-    enum swim_ev_mask {
-        SWIM_EV_NEW             = 0b00000001,
-        SWIM_EV_NEW_STATUS      = 0b00000010,
-        SWIM_EV_NEW_URI         = 0b00000100,
-        SWIM_EV_NEW_GENERATION  = 0b00001000,
-        SWIM_EV_NEW_VERSION     = 0b00010000,
-        SWIM_EV_NEW_INCARNATION = 0b00011000,
-        SWIM_EV_NEW_PAYLOAD     = 0b00100000,
-        SWIM_EV_UPDATE          = 0b00111110,
-        SWIM_EV_DROP            = 0b01000000,
-    };
-
-    struct swim_incarnation {
-        uint64_t generation;
-        uint64_t version;
-    };
-
-    bool
-    swim_is_configured(const struct swim *swim);
-
-    int
-    swim_cfg(struct swim *swim, const char *uri, double heartbeat_rate,
-             double ack_timeout, enum swim_gc_mode gc_mode,
-             const struct tt_uuid *uuid);
-
-    int
-    swim_set_payload(struct swim *swim, const char *payload, int payload_size);
-
-    int
-    swim_set_codec(struct swim *swim, enum crypto_algo algo,
-                   enum crypto_mode mode, const char *key, int key_size);
-
-    int
-    swim_add_member(struct swim *swim, const char *uri,
-                    const struct tt_uuid *uuid);
-
-    int
-    swim_remove_member(struct swim *swim, const struct tt_uuid *uuid);
-
-    int
-    swim_probe_member(struct swim *swim, const char *uri);
-
-    int
-    swim_broadcast(struct swim *swim, int port);
-
-    int
-    swim_size(const struct swim *swim);
-
-    void
-    swim_quit(struct swim *swim);
-
-    struct swim_member *
-    swim_self(struct swim *swim);
-
-    struct swim_member *
-    swim_member_by_uuid(struct swim *swim, const struct tt_uuid *uuid);
-
-    enum swim_member_status
-    swim_member_status(const struct swim_member *member);
-
-    struct swim_iterator *
-    swim_iterator_open(struct swim *swim);
-
-    struct swim_member *
-    swim_iterator_next(struct swim_iterator *iterator);
-
-    void
-    swim_iterator_close(struct swim_iterator *iterator);
-
-    const char *
-    swim_member_uri(const struct swim_member *member);
-
-    const struct tt_uuid *
-    swim_member_uuid(const struct swim_member *member);
-
-    struct swim_incarnation
-    swim_member_incarnation(const struct swim_member *member);
-
-    const char *
-    swim_member_payload(const struct swim_member *member, int *size);
-
-    void
-    swim_member_ref(struct swim_member *member);
-
-    void
-    swim_member_unref(struct swim_member *member);
-
-    bool
-    swim_member_is_dropped(const struct swim_member *member);
-
-    bool
-    swim_member_is_payload_up_to_date(const struct swim_member *member);
-]]
-
 -- Shortcut to avoid unnecessary lookups in 'ffi' table.
 local capi = ffi.C
 
diff --git a/src/lua/title.lua b/src/lua/title.lua
index 22ff0435c..6880ff8c0 100644
--- a/src/lua/title.lua
+++ b/src/lua/title.lua
@@ -1,16 +1,4 @@
 local ffi = require('ffi')
-ffi.cdef[[
-    void title_update();
-    const char *title_get();
-    void title_set_interpretor_name(const char *);
-    const char *title_get_interpretor_name();
-    void title_set_script_name(const char *);
-    const char *title_get_script_name();
-    void title_set_custom(const char *);
-    const char *title_get_custom();
-    void title_set_status(const char *);
-    const char *title_get_status();
-]]
 
 local title = {}
 
diff --git a/src/lua/uri.lua b/src/lua/uri.lua
index 5967c8bf2..67fa18717 100644
--- a/src/lua/uri.lua
+++ b/src/lua/uri.lua
@@ -3,34 +3,6 @@
 local ffi = require('ffi')
 local static_alloc = require('buffer').static_alloc
 
-ffi.cdef[[
-struct uri {
-    const char *scheme;
-    size_t scheme_len;
-    const char *login;
-    size_t login_len;
-    const char *password;
-    size_t password_len;
-    const char *host;
-    size_t host_len;
-    const char *service;
-    size_t service_len;
-    const char *path;
-    size_t path_len;
-    const char *query;
-    size_t query_len;
-    const char *fragment;
-    size_t fragment_len;
-    int host_hint;
-};
-
-int
-uri_parse(struct uri *uri, const char *str);
-
-int
-uri_format(char *str, size_t len, struct uri *uri, bool write_password);
-]]
-
 local builtin = ffi.C;
 
 local function parse(str)
diff --git a/src/lua/utils.h b/src/lua/utils.h
index d9fb0704f..85a469c02 100644
--- a/src/lua/utils.h
+++ b/src/lua/utils.h
@@ -69,7 +69,9 @@ struct ibuf;
  * snprintf(m_errmsg, sizeof(m_errmsg), "%s", msg ? msg : "");
  */
 extern struct lua_State *tarantool_L;
+/** \cond ffi */
 extern struct ibuf *tarantool_lua_ibuf;
+/** \endcond ffi */
 
 extern uint32_t CTID_CONST_CHAR_PTR;
 extern uint32_t CTID_CHAR_PTR;
diff --git a/src/lua/uuid.lua b/src/lua/uuid.lua
index f8418cf4d..a74b215a6 100644
--- a/src/lua/uuid.lua
+++ b/src/lua/uuid.lua
@@ -4,33 +4,6 @@ local ffi = require("ffi")
 local static_alloc = require('buffer').static_alloc
 local builtin = ffi.C
 
-ffi.cdef[[
-struct tt_uuid {
-    uint32_t time_low;
-    uint16_t time_mid;
-    uint16_t time_hi_and_version;
-    uint8_t clock_seq_hi_and_reserved;
-    uint8_t clock_seq_low;
-    uint8_t node[6];
-};
-
-void
-tt_uuid_create(struct tt_uuid *uu);
-int
-tt_uuid_from_string(const char *in, struct tt_uuid *uu);
-void
-tt_uuid_to_string(const struct tt_uuid *uu, char *out);
-void
-tt_uuid_bswap(struct tt_uuid *uu);
-bool
-tt_uuid_is_nil(const struct tt_uuid *uu);
-bool
-tt_uuid_is_equal(const struct tt_uuid *lhs, const struct tt_uuid *rhs);
-char *
-tt_uuid_str(const struct tt_uuid *uu);
-extern const struct tt_uuid uuid_nil;
-]]
-
 local uuid_t = ffi.typeof('struct tt_uuid')
 local UUID_STR_LEN = 36
 local UUID_LEN = ffi.sizeof(uuid_t)
diff --git a/src/main.h b/src/main.h
index f509e905b..37b7ad633 100644
--- a/src/main.h
+++ b/src/main.h
@@ -37,11 +37,15 @@
 extern "C" {
 #endif /* defined(__cplusplus) */
 
+/** \cond ffi */
+
 double tarantool_uptime(void);
 
 void
 tarantool_exit(int);
 
+/** \endcond ffi */
+
 void
 load_cfg();
 
diff --git a/src/scramble.h b/src/scramble.h
index b14a04209..672951e83 100644
--- a/src/scramble.h
+++ b/src/scramble.h
@@ -81,6 +81,8 @@ int
 scramble_check(const void *scramble, const void *salt, const void *hash2);
 
 
+/** \cond ffi */
+
 /**
  * Prepare a password hash as is stored in the _user space.
  * @pre out must be at least SCRAMBLE_BASE64_SIZE
@@ -89,6 +91,8 @@ scramble_check(const void *scramble, const void *salt, const void *hash2);
 void
 password_prepare(const char *password, int len, char *out, int out_len);
 
+/** \endcond ffi */
+
 /**
  * Given a scramble received from a client, salt sent to client,
  * salt received from another instance and user hash2, recalculate
diff --git a/src/title.h b/src/title.h
index 8754d8a55..d2e1f46de 100644
--- a/src/title.h
+++ b/src/title.h
@@ -75,6 +75,8 @@ char **title_init(int argc, char **argv);
 
 void title_free(int argc, char **argv);
 
+/** \cond ffi */
+
 /** generate and update process title */
 void title_update();
 
@@ -96,6 +98,8 @@ const char *title_get_custom();
 void title_set_status(const char *);
 const char *title_get_status();
 
+/** \endcond ffi */
+
 #if defined(__cplusplus)
 } /* extern "C" */
 #endif
diff --git a/test/app/uuid.result b/test/app/uuid.result
index 0713614c6..bb896e2b1 100644
--- a/test/app/uuid.result
+++ b/test/app/uuid.result
@@ -106,7 +106,7 @@ uu.node[5]
 -- invalid values
 uuid.fromstr(nil)
 ---
-- error: 'builtin/uuid.lua:47: fromstr(str)'
+- error: 'builtin/uuid.lua:20: fromstr(str)'
 ...
 uuid.fromstr('')
 ---
-- 
2.17.1



More information about the Tarantool-patches mailing list