c/lua:metatable
This commit is contained in:
125
c/lua/_demo/metatable/metatable.go
Normal file
125
c/lua/_demo/metatable/metatable.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/goplus/llgo/c"
|
||||
"github.com/goplus/llgo/c/lua"
|
||||
)
|
||||
|
||||
func toString(L *lua.State) c.Int {
|
||||
L.Pushstring(c.Str("Hello from metatable!"))
|
||||
return 1
|
||||
}
|
||||
|
||||
func printStack(L *lua.State, message string) {
|
||||
top := L.Gettop()
|
||||
c.Printf(c.Str("%s - Stack size: %d\n"), c.AllocaCStr(message), c.Int(top))
|
||||
for i := c.Int(1); i <= top; i++ {
|
||||
t := L.Type(i)
|
||||
switch t {
|
||||
case c.Int(lua.STRING):
|
||||
c.Printf(c.Str(" %d: string: %s\n"), c.Int(i), L.Tostring(i))
|
||||
case c.Int(lua.BOOLEAN):
|
||||
c.Printf(c.Str(" %d: boolean: %v\n"), c.Int(i), L.Toboolean(i))
|
||||
case c.Int(lua.NUMBER):
|
||||
c.Printf(c.Str(" %d: number: %f\n"), c.Int(i), L.Tonumber(i))
|
||||
default:
|
||||
c.Printf(c.Str(" %d: %s\n"), c.Int(i), L.Typename(t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
L := lua.Newstate()
|
||||
defer L.Close()
|
||||
|
||||
L.Openlibs()
|
||||
|
||||
L.Newtable()
|
||||
printStack(L, "After creating main table")
|
||||
|
||||
L.Newtable()
|
||||
printStack(L, "After creating metatable")
|
||||
|
||||
L.Pushcfunction(toString)
|
||||
printStack(L, "After Push CFunction")
|
||||
|
||||
L.Setfield(-2, c.Str("__tostring"))
|
||||
printStack(L, "After setting __tostring")
|
||||
|
||||
if L.Setmetatable(-2) == 0 {
|
||||
c.Printf(c.Str("Failed to set metatable\n"))
|
||||
}
|
||||
printStack(L, "After setting metatable")
|
||||
|
||||
L.Setglobal(c.Str("obj"))
|
||||
printStack(L, "After setting global obj")
|
||||
|
||||
testcode := c.Str(`
|
||||
if obj == nil then
|
||||
print('obj is not defined')
|
||||
else
|
||||
local mt = getmetatable(obj)
|
||||
if not mt then
|
||||
print('Metatable not set')
|
||||
elseif not mt.__tostring then
|
||||
print('__tostring not set in metatable')
|
||||
else
|
||||
print(mt.__tostring(obj))
|
||||
end
|
||||
end
|
||||
`)
|
||||
|
||||
if L.Dostring(testcode) != lua.OK {
|
||||
c.Printf(c.Str("Error: %s\n"), L.Tostring(-1))
|
||||
}
|
||||
|
||||
L.Getglobal(c.Str("obj"))
|
||||
if L.Getmetatable(-1) != 0 {
|
||||
c.Printf(c.Str("Metatable get success\n"))
|
||||
L.Pushstring(c.Str("__tostring"))
|
||||
L.Gettable(-2)
|
||||
if L.Isfunction(-1) {
|
||||
c.Printf(c.Str("__tostring function found in metatable\n"))
|
||||
if L.Iscfunction(-1) != 0 {
|
||||
c.Printf(c.Str("__tostring is a C function\n"))
|
||||
cfunc := L.Tocfunction(-1)
|
||||
if cfunc != nil {
|
||||
c.Printf(c.Str("Successfully retrieved __tostring C function pointer\n"))
|
||||
L.Pushcfunction(cfunc)
|
||||
if L.Call(0, 1) == lua.OK {
|
||||
result := L.Tostring(-1)
|
||||
c.Printf(c.Str("Result of calling __tostring: %s\n"), result)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
c.Printf(c.Str("__tostring function not found in metatable\n"))
|
||||
}
|
||||
} else {
|
||||
c.Printf(c.Str("No metatable found using GetTable\n"))
|
||||
}
|
||||
}
|
||||
|
||||
/* Expected output:
|
||||
After creating main table - Stack size: 1
|
||||
1: table
|
||||
After creating metatable - Stack size: 2
|
||||
1: table
|
||||
2: table
|
||||
After Push CFunction - Stack size: 3
|
||||
1: table
|
||||
2: table
|
||||
3: function
|
||||
After setting __tostring - Stack size: 2
|
||||
1: table
|
||||
2: table
|
||||
After setting metatable - Stack size: 1
|
||||
1: table
|
||||
After setting global obj - Stack size: 0
|
||||
Hello from metatable!
|
||||
Metatable get success
|
||||
__tostring function found in metatable
|
||||
__tostring is a C function
|
||||
Successfully retrieved __tostring C function pointer
|
||||
Result of calling __tostring: Hello from metatable!
|
||||
*/
|
||||
124
c/lua/lua.go
124
c/lua/lua.go
@@ -41,17 +41,17 @@ type State struct {
|
||||
// ** basic types
|
||||
// */
|
||||
const (
|
||||
NONE = int(-1)
|
||||
NIL = int(0)
|
||||
BOOLEAN = int(1)
|
||||
LIGHTUSERDATA = int(2)
|
||||
NUMBER = int(3)
|
||||
STRING = int(4)
|
||||
TABLE = int(5)
|
||||
FUNCTION = int(6)
|
||||
USERDATA = int(7)
|
||||
THREAD = int(8)
|
||||
UMTYPES = int(9)
|
||||
NONE c.Int = -1
|
||||
NIL c.Int = 0
|
||||
BOOLEAN c.Int = 1
|
||||
LIGHTUSERDATA c.Int = 2
|
||||
NUMBER c.Int = 3
|
||||
STRING c.Int = 4
|
||||
TABLE c.Int = 5
|
||||
FUNCTION c.Int = 6
|
||||
USERDATA c.Int = 7
|
||||
THREAD c.Int = 8
|
||||
UMTYPES c.Int = 9
|
||||
)
|
||||
|
||||
// /* minimum Lua stack available to a C function */
|
||||
@@ -78,13 +78,15 @@ type Integer = c.Int
|
||||
type Unsigned = c.Uint
|
||||
|
||||
// /* type for continuation-function contexts */
|
||||
// TODO(zzy): Context may not be c.Int
|
||||
type KContext c.Int
|
||||
type KContext = c.Pointer
|
||||
|
||||
// /*
|
||||
// ** Type for C functions registered with Lua
|
||||
// */
|
||||
|
||||
// llgo:type C
|
||||
type CFunction func(L *State) c.Int
|
||||
|
||||
// /*
|
||||
// ** Type for continuation functions
|
||||
// */
|
||||
@@ -185,9 +187,6 @@ func (L *State) Xmove(to *State, n c.Int) {}
|
||||
// /*
|
||||
// ** access functions (stack -> C)
|
||||
// */
|
||||
// LUA_API int (lua_isinteger) (State *L, int idx);
|
||||
// llgo:link (*State).Isinteger C.lua_isinteger
|
||||
func (L *State) Isinteger(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).Isnumber C.lua_isnumber
|
||||
func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
||||
@@ -195,11 +194,17 @@ func (L *State) Isnumber(idx c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Isstring C.lua_isstring
|
||||
func (L *State) Isstring(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// TODO(zzy):add to demo
|
||||
// llgo:link (*State).Iscfunction C.lua_iscfunction
|
||||
func (L *State) Iscfunction(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).Isinteger C.lua_isinteger
|
||||
func (L *State) Isinteger(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
||||
|
||||
// llgo:link (*State).Type C.lua_type
|
||||
func (L *State) Type(idx c.Int) c.Int { return 0 }
|
||||
|
||||
// TODO(zzy)
|
||||
// llgo:link (*State).Typename C.lua_typename
|
||||
func (L *State) Typename(tp c.Int) *c.Char { return nil }
|
||||
|
||||
@@ -215,11 +220,11 @@ func (L *State) Toboolean(idx c.Int) bool { return false }
|
||||
// llgo:link (*State).Tolstring C.lua_tolstring
|
||||
func (L *State) Tolstring(idx c.Int, len *c.Ulong) *c.Char { return nil }
|
||||
|
||||
// LUA_API int (lua_iscfunction) (State *L, int idx);
|
||||
// LUA_API int (lua_isuserdata) (State *L, int idx);
|
||||
|
||||
// LUA_API lua_Unsigned (lua_rawlen) (State *L, int idx);
|
||||
// LUA_API lua_CFunction (lua_tocfunction) (State *L, int idx);
|
||||
|
||||
// llgo:link (*State).Tocfunction C.lua_tocfunction
|
||||
func (L *State) Tocfunction(idx c.Int) CFunction { return nil }
|
||||
|
||||
// LUA_API void *(lua_touserdata) (State *L, int idx);
|
||||
// LUA_API State *(lua_tothread) (State *L, int idx);
|
||||
// LUA_API const void *(lua_topointer) (State *L, int idx);
|
||||
@@ -240,24 +245,21 @@ func (L *State) Pushnumber(n Number) {}
|
||||
// llgo:link (*State).Pushinteger C.lua_pushinteger
|
||||
func (L *State) Pushinteger(n Integer) {}
|
||||
|
||||
// llgo:link (*State).Pushstring C.lua_pushstring
|
||||
func (L *State) Pushstring(s *c.Char) *c.Char {
|
||||
return nil
|
||||
}
|
||||
|
||||
// llgo:link (*State).Pushlstring C.lua_pushlstring
|
||||
func (L *State) Pushlstring(s *c.Char, len c.Ulong) *c.Char {
|
||||
return nil
|
||||
}
|
||||
func (L *State) Pushlstring(s *c.Char, len c.Ulong) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).Pushstring C.lua_pushstring
|
||||
func (L *State) Pushstring(s *c.Char) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).Pushfstring C.lua_pushfstring
|
||||
func (L *State) Pushfstring(format *c.Char, __llgo_va_list ...any) *c.Char { return nil }
|
||||
|
||||
// llgo:link (*State).Pushcclosure C.lua_pushcclosure
|
||||
func (L *State) Pushcclosure(fn CFunction, n c.Int) {}
|
||||
|
||||
// llgo:link (*State).Pushboolean C.lua_pushboolean
|
||||
func (L *State) Pushboolean(b c.Int) {}
|
||||
|
||||
//const char *(lua_pushvfstring) (State *L, const char *fmt,va_list argp);
|
||||
//void (lua_pushcclosure) (State *L, lua_CFunction fn, int n);
|
||||
//void (lua_pushlightuserdata) (State *L, void *p);
|
||||
//int (lua_pushthread) (State *L);
|
||||
|
||||
@@ -274,23 +276,25 @@ func (L *State) Gettable(idx c.Int) c.Int { return 0 }
|
||||
// llgo:link (*State).Getfield C.lua_getfield
|
||||
func (L *State) Getfield(idx c.Int, k *c.Char) c.Int { return 0 }
|
||||
|
||||
// llgo:link (*State).Createtable C.lua_createtable
|
||||
func (L *State) Createtable(narr c.Int, nrec c.Int) {}
|
||||
|
||||
// LUA_API int (lua_geti) (State *L, int idx, lua_Integer n);
|
||||
// LUA_API int (lua_rawget) (State *L, int idx);
|
||||
// LUA_API int (lua_rawgeti) (State *L, int idx, lua_Integer n);
|
||||
// LUA_API int (lua_rawgetp) (State *L, int idx, const void *p);
|
||||
|
||||
// llgo:link (*State).Createtable C.lua_createtable
|
||||
func (L *State) Createtable(narr c.Int, nrec c.Int) {}
|
||||
|
||||
// LUA_API void *(lua_newuserdatauv) (State *L, size_t sz, int nuvalue);
|
||||
// LUA_API int (lua_getmetatable) (State *L, int objindex);
|
||||
|
||||
// llgo:link (*State).Getmetatable C.lua_getmetatable
|
||||
func (L *State) Getmetatable(objindex c.Int) c.Int { return 0 }
|
||||
|
||||
// LUA_API int (lua_getiuservalue) (State *L, int idx, int n);
|
||||
|
||||
// /*
|
||||
// ** set functions (stack -> Lua)
|
||||
// */
|
||||
|
||||
// TODO(zzy):add to demo
|
||||
// llgo:link (*State).Setglobal C.lua_setglobal
|
||||
func (L *State) Setglobal(name *c.Char) {}
|
||||
|
||||
@@ -304,25 +308,34 @@ func (L *State) Setfield(idx c.Int, k *c.Char) {}
|
||||
//void (lua_rawset) (State *L, int idx);
|
||||
//void (lua_rawseti) (State *L, int idx, lua_Integer n);
|
||||
//void (lua_rawsetp) (State *L, int idx, const void *p);
|
||||
//int (lua_setmetatable) (State *L, int objindex);
|
||||
|
||||
// llgo:link (*State).Setmetatable C.lua_setmetatable
|
||||
func (L *State) Setmetatable(objindex c.Int) c.Int { return 0 }
|
||||
|
||||
//int (lua_setiuservalue) (State *L, int idx, int n);
|
||||
|
||||
// /*
|
||||
// ** 'load' and 'call' functions (load and run Lua code)
|
||||
// */
|
||||
|
||||
// llgo:link (*State).Callk C.lua_callk
|
||||
func (L *State) Callk(nargs c.Int, nresults c.Int, ctx KContext, k KFunction) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (L *State) Call(nargs c.Int, nresults c.Int) c.Int {
|
||||
return L.Callk(nargs, nresults, nil, nil)
|
||||
}
|
||||
|
||||
// llgo:link (*State).Pcallk C.lua_pcallk
|
||||
func (L *State) Pcallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k *KFunction) c.Int {
|
||||
func (L *State) Pcallk(nargs c.Int, nresults c.Int, errfunc c.Int, ctx KContext, k KFunction) c.Int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (L *State) Pcall(nargs c.Int, nresults c.Int, errfunc c.Int) c.Int {
|
||||
return L.Pcallk(nargs, nresults, errfunc, KContext(c.Int(0)), nil)
|
||||
return L.Pcallk(nargs, nresults, errfunc, nil, nil)
|
||||
}
|
||||
|
||||
// void (lua_callk) (State *L, int nargs, int nresults, lua_KContext ctx, lua_KFunction k);
|
||||
// #define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL)
|
||||
|
||||
// int (lua_load) (State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode);
|
||||
|
||||
// int (lua_dump) (State *L, lua_Writer writer, void *data, int strip);
|
||||
@@ -396,11 +409,17 @@ func (L *State) Next(idx c.Int) c.Int { return 0 }
|
||||
// ** ===============================================================
|
||||
// */
|
||||
|
||||
func (L *State) Tonumber(idx c.Int) Number { return L.Tonumberx(idx, nil) }
|
||||
func (L *State) Tostring(idx c.Int) *c.Char { return L.Tolstring(idx, nil) }
|
||||
func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
|
||||
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
|
||||
func (L *State) Newtable() { L.Createtable(0, 0) }
|
||||
// #define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
||||
|
||||
func (L *State) Tonumber(idx c.Int) Number { return L.Tonumberx(idx, nil) }
|
||||
func (L *State) Tostring(idx c.Int) *c.Char { return L.Tolstring(idx, nil) }
|
||||
func (L *State) Tointeger(idx c.Int) Integer { return L.Tointegerx(idx, nil) }
|
||||
func (L *State) Pop(n c.Int) { L.Settop(-(n) - 1) }
|
||||
func (L *State) Newtable() { L.Createtable(0, 0) }
|
||||
|
||||
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
func (L *State) Pushcfunction(f CFunction) { L.Pushcclosure(f, 0) }
|
||||
|
||||
func (L *State) Isfunction(n c.Int) bool { return L.Type(n) == c.Int(FUNCTION) }
|
||||
func (L *State) Istable(n c.Int) bool { return L.Type(n) == c.Int(TABLE) }
|
||||
func (L *State) Islightuserdata(n c.Int) bool { return L.Type(n) == c.Int(LIGHTUSERDATA) }
|
||||
@@ -410,20 +429,11 @@ func (L *State) Isthread(n c.Int) bool { return L.Type(n) == c.Int(THREAD
|
||||
func (L *State) Isnone(n c.Int) bool { return L.Type(n) == c.Int(NONE) }
|
||||
func (L *State) Isnoneornil(n c.Int) bool { return L.Type(n) <= 0 }
|
||||
|
||||
// #define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE))
|
||||
|
||||
// #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))
|
||||
|
||||
// #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0)
|
||||
|
||||
// #define lua_pushliteral(L, s) lua_pushstring(L, "" s)
|
||||
|
||||
// #define lua_pushglobaltable(L) ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
|
||||
|
||||
// #define lua_insert(L,idx) lua_rotate(L, (idx), 1)
|
||||
|
||||
// #define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1))
|
||||
|
||||
// #define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1))
|
||||
|
||||
// /* }============================================================== */
|
||||
|
||||
Reference in New Issue
Block a user