Simple Cpp Binding


Description

Here is an example of a Lua binding for a simple C++ class. If you prefer, you can factor out all the nasty bits and put them in a template. SimplerCppBinding shows how to do this using Luna for Lua 5.0

C++ code

extern "C" {
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
class Account {
 public:
 Account(double balance) { m_balance = balance; }
 void deposit(double amount) { m_balance += amount; }
 void withdraw(double amount) { m_balance -= amount; }
 double balance(void) { return m_balance; }
 private:
 double m_balance;
};
class LuaAccount {
 static const char className[];
 static const luaL_reg methods[];
 static Account *checkaccount(lua_State *L, int narg) {
 luaL_checktype(L, narg, LUA_TUSERDATA);
 void *ud = luaL_checkudata(L, narg, className);
 if(!ud) luaL_typerror(L, narg, className);
 return *(Account**)ud; // unbox pointer
 }
 static int create_account(lua_State *L) {
 double balance = luaL_checknumber(L, 1);
 Account *a = new Account(balance);
 lua_boxpointer(L, a);
 luaL_getmetatable(L, className);
 lua_setmetatable(L, -2);
 return 1;
 }
 static int deposit(lua_State *L) {
 Account *a = checkaccount(L, 1);
 double amount = luaL_checknumber(L, 2);
 a->deposit(amount);
 return 0;
 }
 static int withdraw(lua_State *L) {
 Account *a = checkaccount(L, 1);
 double amount = luaL_checknumber(L, 2);
 a->withdraw(amount);
 return 0;
 }
 static int balance(lua_State *L) {
 Account *a = checkaccount(L, 1);
 double balance = a->balance();
 lua_pushnumber(L, balance);
 return 1;
 }
 static int gc_account(lua_State *L) {
 Account *a = (Account*)lua_unboxpointer(L, 1);
 delete a;
 return 0;
 }
 public:
 static void Register(lua_State* L) {
 lua_newtable(L); int methodtable = lua_gettop(L);
 luaL_newmetatable(L, className); int metatable = lua_gettop(L);
 lua_pushliteral(L, "__metatable");
 lua_pushvalue(L, methodtable);
 lua_settable(L, metatable); // hide metatable from Lua getmetatable()
 lua_pushliteral(L, "__index");
 lua_pushvalue(L, methodtable);
 lua_settable(L, metatable);
 lua_pushliteral(L, "__gc");
 lua_pushcfunction(L, gc_account);
 lua_settable(L, metatable);
 lua_pop(L, 1); // drop metatable
 luaL_openlib(L, 0, methods, 0); // fill methodtable
 lua_pop(L, 1); // drop methodtable
 lua_register(L, className, create_account);
 }
};
const char LuaAccount::className[] = "Account";
#define method(class, name) {#name, class::name}
const luaL_reg LuaAccount::methods[] = {
 method(LuaAccount, deposit),
 method(LuaAccount, withdraw),
 method(LuaAccount, balance),
 {0,0}
};
int main(int argc, char* argv[])
{
 lua_State *L = lua_open();
 luaopen_base(L);
 luaopen_table(L);
 luaopen_io(L);
 luaopen_string(L);
 luaopen_math(L);
 luaopen_debug(L);
 LuaAccount::Register(L);
 if(argc>1) lua_dofile(L, argv[1]);
 lua_close(L);
 return 0;
}

Compiling the Code

This code can be compiled for Lua 5.0 as follows:

g++ -o test account.cc -L/usr/local/lib -llua -llualib

Lua Test Code

function printf(...) io.write(string.format(unpack(arg))) end
local a = Account(100)
printf("Account balance = $%0.02f\n", a:balance() )
a:deposit(50.30)
printf("Account balance = $%0.02f\n", a:balance() )
a:withdraw(25.10)
printf("Account balance = $%0.02f\n", a:balance() )

Test Code Output

$ ./test account.lua
Account balance = 100ドル.00
Account balance = 150ドル.30
Account balance = 125ドル.20

RecentChanges · preferences
edit · history
Last edited May 4, 2012 9:54 pm GMT (diff)

AltStyle によって変換されたページ (->オリジナル) /