About me Johnson Lin Programmer & Indie Game igdshare.org & Game Jam! (4/28 ~ 4/29) ( 獨立遊戲開發者分享會 ) archilife.org & Indie game contests scholarship ( 祐生研究基金會 )
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 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 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
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
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 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
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) 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 LuaJIT 2.1 garbage collector redesign Other unconfirmed: FFI C preprocessor? Introduction to LuaJIT
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) //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++
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 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 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' 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' 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' 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
-- 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 LuaJIT Foreign Function Interface Examples of LuaJIT FFI
//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 ]] 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? //after including binding target classes using namespace ns; extern "C" { #include "header.h" } LuaJIT Foreign Function Interface Our problems & solutions
shared_ptrs are all over the place! //No problem typedef shared_ptr 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 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
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