Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to LuaJIT & How to bind CPP code b...

IGDSHARE
April 15, 2012

Introduction to LuaJIT & How to bind CPP code base using LuaJIT FFI

This was presented at osdc.tw/2012, if you find anything wrong, please contact me!

[email protected] or
[email protected]

IGDSHARE

April 15, 2012
Tweet

More Decks by IGDSHARE

Other Decks in Programming

Transcript

  1. Introduction to LuaJIT & How to bind C++ code base

    using LuaJIT FFI 2012.04.14 OSDC.tw
  2. About me Johnson Lin Programmer & Indie Game igdshare.org &

    Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 )
  3. About me Johnson Lin Programmer & Indie Game igdshare.org &

    Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 ) archilife.org ( 祐生研究基金會 )
  4. About me Johnson Lin Programmer & Indie Game igdshare.org &

    Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 ) archilife.org & Indie game contests scholarship ( 祐生研究基金會 )
  5. Overview Introduction to Lua Introduction to LuaJIT How does Lua

    talk to C/C++ LuaJIT FFI (Foreign Function Interface)
  6. Overview Introduction to Lua Introduction to LuaJIT How does Lua

    talk to C/C++ LuaJIT FFI (Foreign Function Interface)
  7. Introduction to LUA Introduction to LUA LUA is... Lua Uppercase

    Accident This pun came from a clever guy Joseph Manning: http://lua-users.org/lists/lua-l/2011-06/msg01112.html
  8. Introduction to Lua Lua = "Moon" in Portuguese Use Cases

    (Game Dev): Grim Fandango, Introduction to Lua
  9. Introduction to Lua Lua = "Moon" in Portuguese Use Cases

    (Game Dev): Grim Fandango, World of Warcraft UI, Introduction to Lua
  10. Introduction to Lua Lua = "Moon" in Portuguese Use Cases

    (Game Dev): Grim Fandango, World of Warcraft UI, Angry Birds Introduction to Lua
  11. Introduction to Lua By Tecgraf / PUC-Rio (1993): Roberto Ierusalimschy,

    Luiz Henrique de Figueiredo, Waldemar Celes Introduction to Lua
  12. Introduction to Lua By Tecgraf / PUC-Rio (1993): Roberto Ierusalimschy,

    Luiz Henrique de Figueiredo, Waldemar Celes Current version: 5.2.0 / 5.1.5 MIT License since 5.0 (BSD License before then) Introduction to Lua
  13. Lua Features Fast Fastest among other well-known interpreted language Small

    ~150kB binary, ~20kB mem overhead per interpreter Introduction to Lua
  14. Lua Features Fast Fastest among other well-known interpreted language Small

    ~150kB binary, ~20kB mem overhead per interpreter Simple 22 keywords, 27 tokens Introduction to Lua
  15. Lua Features Multithreading-Friendly multiple interpreters in multiple threads concurrently without

    GIL Easy to Embed & Extend concise Lua/C API Introduction to Lua
  16. Lua Features Multithreading-Friendly multiple interpreters in multiple threads concurrently without

    GIL Easy to Embed & Extend concise Lua/C API But, without "battery" although Luarocks is in place Introduction to Lua
  17. Z Combinator in Lua Introduction to Lua local Y =

    function(f) return (function(x) return f (function(y) return (x(x))(y) end) end) (function(x) return f (function(y) return (x(x))(y) end) end) end
  18. Overview Introduction to Lua Introduction to LuaJIT How does Lua

    talk to C/C++ LuaJIT FFI (Foreign Function Interface)
  19. Introduction to LuaJIT Just-In-Time compiler for Lua Mike Pall LuaJIT1

    (2005~, current 1.1.7) LuaJIT2 (2009~, current 2.0-beta9) Introduction to LuaJIT
  20. LuaJIT2 Features Interpreter written in assembler (DynASM) Trace compiler x86/64

    (Windows, OSX, Linux, etc) SSE2 instructions required Introduction to LuaJIT
  21. LuaJIT2 Features Interpreter written in assembler (DynASM) Trace compiler x86/64

    (Windows, OSX, Linux, etc) SSE2 instructions required ARM (Android, iOS, etc), PPC, MIPS only the interpreter part on iOS works now, blame Apple Introduction to LuaJIT
  22. LuaJIT2 Features API & ABI compatible with Lua 5.1 Bytecode

    NOT compatible Introduction to LuaJIT
  23. LuaJIT2 Features API & ABI compatible with Lua 5.1 Bytecode

    NOT compatible Some Lua 5.2 functionality But not going to fully catch up anytime soon Introduction to LuaJIT
  24. LuaJIT2 Features API & ABI compatible with Lua 5.1 Bytecode

    NOT compatible Some Lua 5.2 functionality But not going to fully catch up anytime soon Foreign Function Interface with C parser and a few extensions Introduction to LuaJIT
  25. Some Use Cases of LuaJIT AI Implementation in The Settlers

    7 (2010) GSL Shell https://github.com/malkia/ufo Includes OpenGL, OpenCL, SDL, ZeroMQ bindings.. OpenResty web framework based on nginx Introduction to LuaJIT
  26. Some benchmarks Game of Life C++ v.s. LuaJIT (using FFI)

    Please keep in mind this benchmark is pretty crude and favors LuaJIT, it just shows one extreme. Introduction to LuaJIT
  27. Some benchmarks Introduction to LuaJIT Pueudo Code: while (true) {

    game.update(); game.render(); end //both update & render has a big 2d loop //doing state update and drawing cells respectively https://github.com/arch-jslin/mysandbox/tree/master/cpp/lifegame_sdl
  28. Some benchmarks Introduction to LuaJIT Pueudo Code: while true do

    game:update() -- JIT kick in game:render() -- JIT kick in end --both update & render has a big 2d loop --doing state update and drawing cells respectively https://github.com/arch-jslin/mysandbox/blob/master/lua/lifegame_ffi_sdl_gl.lua
  29. Some benchmarks Introduction to LuaJIT Pueudo Code: while true do

    game:update() -- JIT back off game:render() -- JIT kick in end --both update & render has a big 2d loop --doing state update and drawing cells respectively
  30. Some benchmarks Introduction to LuaJIT Pueudo Code: while true do

    game:update() -- JIT back off game:render() -- JIT back off end --both update & render has a big 2d loop --doing state update and drawing cells respectively
  31. LuaJIT Roadmap LuaJIT 2.0 almost feature freeze ARM hard-fp support

    looking for sponsor Introduction to LuaJIT
  32. LuaJIT Roadmap LuaJIT 2.0 almost feature freeze ARM hard-fp support

    looking for sponsor LuaJIT 2.1 garbage collector redesign Introduction to LuaJIT
  33. LuaJIT Roadmap LuaJIT 2.0 almost feature freeze ARM hard-fp support

    looking for sponsor LuaJIT 2.1 garbage collector redesign Other unconfirmed: FFI C preprocessor? Introduction to LuaJIT
  34. Overview Introduction to Lua Introduction to LuaJIT How does Lua

    talk to C/C++ LuaJIT FFI (Foreign Function Interface)
  35. How does Lua talk to C/C++ How does Lua talk

    to C/C++ Manipulate lua_State (Lua Stack) Using Lua/C API core library: lua_xxx(); aux library: luaL_xxx();
  36. Lua/C API -- Lua local a, b = func_from_c(2,3) //C

    static int func_from_c(lua_State* L) { int x = luaL_checkint(L, 1); int y = luaL_checkint(L, -1); lua_pushinteger(L, x+y); lua_pushinteger(L, x-y); return 2; } How does Lua talk to C/C++
  37. Lua/C API -- Lua local a, b = func_from_c(2,3) //C

    static int func_from_c(lua_State* L) { int x = luaL_checkint(L, 1); int y = luaL_checkint(L, -1); lua_pushinteger(L, x+y); lua_pushinteger(L, x-y); return 2; } How does Lua talk to C/C++
  38. What about C++ object? How does Lua talk to C/C++

    -- Lua local o = Simple(1) -- C++ obj
  39. What about C++ object? How does Lua talk to C/C++

    -- Lua local o = Simple(1) -- C++ obj //C //Let's see some actual code...
  40. Binding Libaries Luabind - boost & template magic OOLua -

    Macro & template(?) magic How does Lua talk to C/C++
  41. Binding Libaries Luabind - boost & template magic OOLua -

    Macro & template(?) magic Simple Lua Binder - no boost, but still templates How does Lua talk to C/C++
  42. Binding Libaries Luabind - boost & template magic OOLua -

    Macro & template(?) magic Simple Lua Binder - no boost, but still templates ...etc (post talk addition: I am not saying these are bad or what, just our considerations. If you find these tools "just work" for you, then you probably have no reason to abandon them.) How does Lua talk to C/C++
  43. Binding Generators tolua & tolua++ SWIG (post talk addition: I

    am not saying these are bad or what, just our considerations. If you find these tools "just work" for you, then you probably have no reason to abandon them.) How does Lua talk to C/C++
  44. Problem with those Missing feature Code bloat Runtime overhead Yet

    another glue language How does Lua talk to C/C++
  45. Problem with those Missing feature Code bloat Runtime overhead Yet

    another glue language Not sure what to do in case of bugs How does Lua talk to C/C++
  46. Can be JIT compiled Unlike libffi based modules or other

    binding methods LuaJIT Foreign Function Interface LuaJIT FFI
  47. Can be JIT compiled Unlike libffi based modules or other

    binding methods Has a C parser built-in LuaJIT Foreign Function Interface LuaJIT FFI
  48. Can be JIT compiled Unlike libffi based modules or other

    binding methods Has a C parser built-in Pure Lua Syntax So there's got LuaFFI => https://github.com/jmckaskill/luaffi LuaJIT Foreign Function Interface LuaJIT FFI
  49. -- Using C type local ffi = require 'ffi' LuaJIT

    Foreign Function Interface Examples of LuaJIT FFI
  50. -- Using C type local ffi = require 'ffi' local

    a = ffi.new("int") LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  51. -- Using C type local ffi = require 'ffi' local

    a = ffi.new("int") local b = ffi.new("char const*") LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  52. -- Using C type local ffi = require 'ffi' local

    a = ffi.new("int") local b = ffi.new("char const*") local c = ffi.new("double[10]") LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  53. -- Using C type local ffi = require 'ffi' local

    a = ffi.new("int") local b = ffi.new("char const*") local c = ffi.new("double[10]") local d = ffi.new("double[?]", 20) LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  54. -- Calling external C functions local ffi = require 'ffi'

    LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  55. -- Calling external C functions local ffi = require 'ffi'

    local C = ffi.C LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  56. -- Calling external C functions local ffi = require 'ffi'

    local C = ffi.C ffi.cdef[[ int printf(const char*, ...); ]] LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  57. -- Calling external C functions local ffi = require 'ffi'

    local C = ffi.C ffi.cdef[[ int printf(const char*, ...); ]] C.printf('Hello %s!\n', 'world') LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  58. -- Calling external C functions local ffi = require 'ffi'

    local C = ffi.C ffi.cdef[[ int printf(const char*, ...); ]] C.printf('Hello %s!\n', 'world') C.printf('%d', ffi.cast('int', 3)) LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  59. -- Calling external C functions local ffi = require 'ffi'

    LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  60. -- Calling external C functions local ffi = require 'ffi'

    ffi.cdef[[ typedef struct { int x,y,z; } Point; void do_stuff(Point*); ]] LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  61. -- Calling external C functions local ffi = require 'ffi'

    ffi.cdef[[ typedef struct { int x,y,z; } Point; void do_stuff(Point*); ]] LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  62. -- Calling external C functions local ffi = require 'ffi'

    ffi.cdef[[ typedef struct { int x,y,z; } Point; void do_stuff(Point*); ]] LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  63. -- Calling external C functions local ffi = require 'ffi'

    ffi.cdef[[ typedef struct { int x,y,z; } Point; void do_stuff(Point*); ]] local Lib = ffi.load('path/to/your_c_lib') LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  64. -- Calling external C functions local ffi = require 'ffi'

    ffi.cdef[[ typedef struct { int x,y,z; } Point; void do_stuff(Point*); ]] local Lib = ffi.load('path/to/your_c_lib') local a = ffi.new('Point', 1, 2, 3) LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  65. -- Calling external C functions local ffi = require 'ffi'

    ffi.cdef[[ typedef struct { int x,y,z; } Point; void do_stuff(Point*); ]] local Lib = ffi.load('path/to/your_c_lib') local a = ffi.new('Point', 1, 2, 3) Lib.do_stuff(a) LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  66. -- Using C header directly (almost) local ffi = require

    'ffi' LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  67. -- Using C header directly (almost) local ffi = require

    'ffi' ffi.cdef(io.open('header.h', 'r'):read('*a')) LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  68. -- Using C header directly (almost) local ffi = require

    'ffi' ffi.cdef(io.open('header.h', 'r'):read('*a')) -- This header.h has to be preprocessed LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  69. -- Using C header directly (almost) local ffi = require

    'ffi' ffi.cdef(io.open('header.h', 'r'):read('*a')) -- This header.h has to be preprocessed -- gcc -E stub.c | grep -v '^#' LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  70. -- Using C header directly (almost) local ffi = require

    'ffi' ffi.cdef(io.open('header.h', 'r'):read('*a')) -- This header.h has to be preprocessed -- gcc -E stub.c | grep -v '^#' -- stub.c only contain #include <header.h> LuaJIT Foreign Function Interface Examples of LuaJIT FFI
  71. //C++ side class A { public: void method(); }; LuaJIT

    Foreign Function Interface But, in case of C++
  72. //C++ side class A { public: void method(); }; extern

    "C" { A* A_new() { return new A; } void A_method(A* self) { self->method(); } void A_gc(A* self) { delete self; } } LuaJIT Foreign Function Interface But, in case of C++
  73. //C++ side class A { public: void method(); }; extern

    "C" { A* A_new() { return new A; } void A_method(A* self) { self->method(); } void A_gc(A* self) { delete self; } } LuaJIT Foreign Function Interface But, in case of C++
  74. //C++ side class A { public: void method(); }; extern

    "C" { A* A_new() { return new A; } void A_method(A* self) { self->method(); } void A_gc(A* self) { delete self; } } LuaJIT Foreign Function Interface But, in case of C++
  75. //C++ side class A { public: void method(); }; extern

    "C" { //as before, export these A* A_new() { return new A; } void A_method(A* self) { self->method(); } void A_gc(A* self) { delete self; } } LuaJIT Foreign Function Interface But, in case of C++
  76. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] LuaJIT Foreign Function Interface But, in case of C++
  77. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] LuaJIT Foreign Function Interface But, in case of C++
  78. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] local lib = ffi.load('/path/to/lib') LuaJIT Foreign Function Interface But, in case of C++
  79. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] local lib = ffi.load('/path/to/lib') local mt = {} LuaJIT Foreign Function Interface But, in case of C++
  80. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] local lib = ffi.load('/path/to/lib') local mt = {} mt.__index = mt LuaJIT Foreign Function Interface But, in case of C++
  81. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] local lib = ffi.load('/path/to/lib') local mt = {} mt.__index = mt mt.method = lib.A_method LuaJIT Foreign Function Interface But, in case of C++
  82. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] local lib = ffi.load('/path/to/lib') local mt = {} mt.__index = mt mt.method = lib.A_method ffi.metatype('A', mt) LuaJIT Foreign Function Interface But, in case of C++
  83. ffi.cdef[[ typedef struct A A; //and then declare identical functions

    ]] local lib = ffi.load('/path/to/lib') local mt = {} mt.__index = mt mt.method = lib.A_method ffi.metatype('A', mt) local a = ffi.gc(lib.A_new(), lib.A_gc) LuaJIT Foreign Function Interface But, in case of C++
  84. How to reuse header.h in case of namespace? LuaJIT Foreign

    Function Interface Our problems & solutions
  85. How to reuse header.h in case of namespace? //after including

    binding target classes using namespace ns; extern "C" { #include "header.h" } LuaJIT Foreign Function Interface Our problems & solutions
  86. How to reuse header.h in case of namespace? //after including

    binding target classes using namespace ns; extern "C" { #include "header.h" } A* A_new() { ... } void A_method(A* self) { ... } void A_gc(A* self) { ... } LuaJIT Foreign Function Interface Our problems & solutions
  87. shared_ptrs are all over the place! //No problem typedef shared_ptr<A>

    pA; just use pA in place of A, it's like a boxed pointer LuaJIT Foreign Function Interface Our problems & solutions
  88. C++ is the main body, Lua is not LuaJIT Foreign

    Function Interface Our problems & solutions
  89. C++ is the main body, Lua is not Use Lua/C

    API to push a handle to Lua side at the very beginning. And everything goes. LuaJIT Foreign Function Interface Our problems & solutions
  90. C++ is the main body, Lua is not Use Lua/C

    API to push a handle to Lua side at the very beginning. And everything goes. (have to export a set of methods of this handle to Lua, too) LuaJIT Foreign Function Interface Our problems & solutions
  91. Some of our binding codes and usages: 1. https://github.com/godfat/cubeat/blob/master/cubeat-core/include/script/ai/bindings.h 2.

    https://github.com/godfat/cubeat/blob/master/cubeat-core/src/script/ai/bindings.cpp 3. https://github.com/godfat/cubeat/blob/master/cubeat-core/rc/script/ai/ai.lua 4. https://github.com/godfat/cubeat/blob/master/cubeat-core/rc/script/ai/normal.lua LuaJIT Foreign Function Interface Our problems & solutions
  92. Lua is cool and LuaJIT is fast LuaJIT FFI is

    a powerful tool for bindings Binding automation can still be done (and a lot easier), Conclusion
  93. Lua is cool and LuaJIT is fast LuaJIT FFI is

    a powerful tool for bindings Binding automation can still be done (and a lot easier), IF NECESSARY Conclusion