Share
Embed
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
Transcript
134 slides
-
Introduction to LuaJIT & How to bind C++ code base
using LuaJIT FFI 2012.04.14 OSDC.tw -
About me Johnson Lin Programmer & Indie Game igdshare.org &
Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 ) -
About me Johnson Lin Programmer & Indie Game igdshare.org &
Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 ) archilife.org ( 祐生研究基金會 ) -
About me Johnson Lin Programmer & Indie Game igdshare.org &
Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 ) archilife.org & Indie game contests scholarship ( 祐生研究基金會 ) -
Overview Introduction to Lua Introduction to LuaJIT How does Lua
talk to C/C++ LuaJIT FFI (Foreign Function Interface) -
Overview Introduction to Lua Introduction to LuaJIT How does Lua
talk to C/C++ LuaJIT FFI (Foreign Function Interface) -
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 -
Introduction to Lua Lua = "Moon" in Portuguese Use Cases
(Game Dev): Introduction to Lua -
Introduction to Lua Lua = "Moon" in Portuguese Use Cases
(Game Dev): Grim Fandango, Introduction to Lua -
Introduction to Lua Lua = "Moon" in Portuguese Use Cases
(Game Dev): Grim Fandango, World of Warcraft UI, Introduction to Lua -
Introduction to Lua Lua = "Moon" in Portuguese Use Cases
(Game Dev): Grim Fandango, World of Warcraft UI, Angry Birds Introduction to Lua -
Introduction to Lua By Tecgraf / PUC-Rio (1993): Roberto Ierusalimschy,
Luiz Henrique de Figueiredo, Waldemar Celes Introduction to Lua -
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 -
Lua Features Fast Fastest among other well-known interpreted language Small
~150kB binary, ~20kB mem overhead per interpreter Introduction to Lua -
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 -
Lua Features Multithreading-Friendly multiple interpreters in multiple threads concurrently without
GIL Easy to Embed & Extend concise Lua/C API Introduction to Lua -
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 -
Lua Features Introduction to Lua Multi-paradigm: procedural functional prototype-based OO
Think Lua as JavaScript -
Lua Features Introduction to Lua Multi-paradigm: procedural functional prototype-based OO
Think Lua as JavaScript .....without the Bad Parts -
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 -
Overview Introduction to Lua Introduction to LuaJIT How does Lua
talk to C/C++ LuaJIT FFI (Foreign Function Interface) -
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 -
LuaJIT2 Features Interpreter written in assembler (DynASM) Trace compiler x86/64
(Windows, OSX, Linux, etc) SSE2 instructions required Introduction to LuaJIT -
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 -
LuaJIT2 Features API & ABI compatible with Lua 5.1 Bytecode
NOT compatible Introduction to LuaJIT -
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 -
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 -
LuaJIT - Behind the Scene Introduction to LuaJIT Too hard
for me! Sorry! -
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 -
Some benchmarks Game of Life C++ v.s. LuaJIT (using FFI)
Introduction to LuaJIT -
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 -
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 -
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 -
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 -
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 -
LuaJIT Roadmap LuaJIT 2.0 almost feature freeze ARM hard-fp support
looking for sponsor Introduction to LuaJIT -
LuaJIT Roadmap LuaJIT 2.0 almost feature freeze ARM hard-fp support
looking for sponsor LuaJIT 2.1 garbage collector redesign Introduction to LuaJIT -
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 -
Overview Introduction to Lua Introduction to LuaJIT How does Lua
talk to C/C++ LuaJIT FFI (Foreign Function Interface) -
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(); -
Lua/C API -- Lua local a, b = func_from_c(2,3) How
does Lua talk to C/C++ -
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++ -
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++ -
What about C++ object? How does Lua talk to C/C++
-- Lua local o = Simple(1) -- C++ obj -
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... -
What about C++ object? How does Lua talk to C/C++
So that's a bit scary.. -
Binding Libaries Luabind - boost & template magic How does
Lua talk to C/C++ -
Binding Libaries Luabind - boost & template magic OOLua -
Macro & template(?) magic How does Lua talk to C/C++ -
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++ -
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++ -
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++ -
Problem with those Missing feature Code bloat Runtime overhead How
does Lua talk to C/C++ -
Problem with those Missing feature Code bloat Runtime overhead Yet
another glue language How does Lua talk to C/C++ -
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++ -
Can be JIT compiled Unlike libffi based modules or other
binding methods LuaJIT Foreign Function Interface LuaJIT FFI -
Can be JIT compiled Unlike libffi based modules or other
binding methods Has a C parser built-in LuaJIT Foreign Function Interface LuaJIT FFI -
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 -
-- Using C type local ffi = require 'ffi' LuaJIT
Foreign Function Interface Examples of LuaJIT FFI -
-- Using C type local ffi = require 'ffi' local
a = ffi.new("int") LuaJIT Foreign Function Interface Examples of LuaJIT FFI -
-- 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 -
-- 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 -
-- 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 -
-- Calling external C functions local ffi = require 'ffi'
LuaJIT Foreign Function Interface Examples of LuaJIT FFI -
-- Calling external C functions local ffi = require 'ffi'
local C = ffi.C LuaJIT Foreign Function Interface Examples of LuaJIT FFI -
-- 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 -
-- 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 -
-- 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 -
-- Calling external C functions local ffi = require 'ffi'
LuaJIT Foreign Function Interface Examples of LuaJIT FFI -
-- 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 -
-- 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 -
-- 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 -
-- 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 -
-- 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 -
-- 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 -
-- Using C header directly (almost) local ffi = require
'ffi' LuaJIT Foreign Function Interface Examples of LuaJIT FFI -
-- 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 -
-- 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 -
-- 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 -
-- 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 -
//C++ side class A { public: void method(); }; LuaJIT
Foreign Function Interface But, in case of C++ -
//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++ -
//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++ -
//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++ -
//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++ -
ffi.cdef[[ typedef struct A A; //and then declare identical functions
]] LuaJIT Foreign Function Interface But, in case of C++ -
ffi.cdef[[ typedef struct A A; //and then declare identical functions
]] LuaJIT Foreign Function Interface But, in case of C++ -
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++ -
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++ -
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++ -
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++ -
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++ -
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++ -
How to reuse header.h in case of namespace? LuaJIT Foreign
Function Interface Our problems & solutions -
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 -
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 -
shared_ptrs are all over the place! LuaJIT Foreign Function Interface
Our problems & solutions -
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 -
C++ is the main body, Lua is not LuaJIT Foreign
Function Interface Our problems & solutions -
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 -
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 -
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 -
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 -
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