aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ClientHamr/GuiLua/test_c.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-03-28 15:44:43 +1000
committerDavid Walter Seikel2014-03-28 15:44:43 +1000
commit5018f9e7673f533bbe3240c2ecce703b47d76a73 (patch)
treec9cfa3b06f3a830d2819ee42ccd50f7a6378f343 /ClientHamr/GuiLua/test_c.c
parentTODO++ (diff)
downloadSledjHamr-5018f9e7673f533bbe3240c2ecce703b47d76a73.zip
SledjHamr-5018f9e7673f533bbe3240c2ecce703b47d76a73.tar.gz
SledjHamr-5018f9e7673f533bbe3240c2ecce703b47d76a73.tar.bz2
SledjHamr-5018f9e7673f533bbe3240c2ecce703b47d76a73.tar.xz
Make test_c a real skang module, and tweaks to the rest of the system to support C skang modules.
Diffstat (limited to 'ClientHamr/GuiLua/test_c.c')
-rw-r--r--ClientHamr/GuiLua/test_c.c177
1 files changed, 131 insertions, 46 deletions
diff --git a/ClientHamr/GuiLua/test_c.c b/ClientHamr/GuiLua/test_c.c
index 8d3ab81..e3fd801 100644
--- a/ClientHamr/GuiLua/test_c.c
+++ b/ClientHamr/GuiLua/test_c.c
@@ -8,9 +8,6 @@ http://lua.2524044.n2.nabble.com/C-Lua-modules-not-compatible-with-every-Lua-int
8http://lua-users.org/wiki/LuaProxyDllFour 8http://lua-users.org/wiki/LuaProxyDllFour
9http://stackoverflow.com/questions/11492194/how-do-you-create-a-lua-plugin-that-calls-the-c-lua-api?rq=1 9http://stackoverflow.com/questions/11492194/how-do-you-create-a-lua-plugin-that-calls-the-c-lua-api?rq=1
10http://lua-users.org/lists/lua-l/2008-01/msg00671.html 10http://lua-users.org/lists/lua-l/2008-01/msg00671.html
11
12
13
14*/ 11*/
15 12
16 13
@@ -19,72 +16,160 @@ http://lua-users.org/lists/lua-l/2008-01/msg00671.html
19//#include <lualib.h> 16//#include <lualib.h>
20 17
21 18
22static int ffunc (lua_State *L) 19static const char *ourName = "test_c";
20int skang, _M;
21
22static int cfunc (lua_State *L)
23{ 23{
24 double arg1 = luaL_checknumber(L, 1); 24 double arg1 = luaL_checknumber(L, 1);
25 const char *arg2 = luaL_checkstring(L, 2); 25 const char *arg2 = luaL_checkstring(L, 2);
26 26
27 printf("Inside test_c.ffunc(%f, %s)\n", arg1, arg2); 27 printf("Inside %s.cfunc(%f, %s)\n", ourName, arg1, arg2);
28 return 0; 28 return 0;
29} 29}
30 30
31 31
32static const struct luaL_reg test_c [] = 32static void dumpStack(lua_State *L, int i)
33{ 33{
34 {"ffunc", ffunc}, 34 int type = lua_type(L, i);
35 {NULL, NULL} 35
36}; 36 switch (type)
37 37 {
38 case LUA_TNONE : printf("Stack %d is empty\n", i); break;
39 case LUA_TNIL : printf("Stack %d is a nil\n", i); break;
40 case LUA_TBOOLEAN : printf("Stack %d is a boolean\n", i); break;
41 case LUA_TNUMBER : printf("Stack %d is a number\n", i); break;
42 case LUA_TSTRING : printf("Stack %d is a string - %s\n", i, lua_tostring(L, i)); break;
43 case LUA_TFUNCTION : printf("Stack %d is a function\n", i); break;
44 case LUA_TTHREAD : printf("Stack %d is a thread\n", i); break;
45 case LUA_TTABLE : printf("Stack %d is a table\n", i); break;
46 case LUA_TUSERDATA : printf("Stack %d is a userdata\n", i); break;
47 case LUA_TLIGHTUSERDATA : printf("Stack %d is a light userdata\n", i); break;
48 default : printf("Stack %d is unknown\n", i); break;
49 }
50}
38 51
39/* local test_c = require 'test_c' 52/* local test_c = require 'test_c'
40 53
41Lua's require() function will strip any stuff from the front of the name 54Lua's require() function will strip any stuff from the front of the name
42separated by a hypen, so 'GuiLua-test_c' -> 'test_c'. Then it will 55separated by a hyphen, so 'GuiLua-test_c' -> 'test_c'. Then it will
43search through a path, and eventually find this test_c.so (or test_c.dll 56search through a path, and eventually find this test_c.so (or test_c.dll
44or whatever), then call luaopen_test_c(), which should return a table. 57or whatever), then call luaopen_test_c(), which should return a table.
58The argument (only thing on the stack) for this function will be
59'test_c'.
45 60
46Normally luaL_register() creates a table of functions, that is the table 61Normally luaL_register() creates a table of functions, that is the table
47returned, but we want to do something different with skang. 62returned, but we want to do something different with skang.
48
49*/ 63*/
50int luaopen_test_c(lua_State *L) 64int luaopen_test_c(lua_State *L)
51{ 65{
52// This is a moving target, old ways get deperecated, new ways get added,
53// would have to check version before doing any of these.
54// luaL_openlib(L, "test_c", test_c, 0); // Lua 5.0 way.
55// luaL_register (L, "test_c", test_c); // Lua 5.1 way.
56// luaL_newlib() or luaL_setfuncs() // Lua 5.2 way.
57 // Creates a global table "test_c", does the package.loaded[test_c] thing.
58 lua_newtable(L);
59 luaL_register (L, NULL, test_c); // Lua 5.1 way.
60 // Puts the funcions in a table on top of the stack.
61
62/* BUT REALLY ...
63
64We are in fact NOT putting any functions into the returned table.
65
66skang.moduleBegin() returns the table we need to send back to Lua.
67 it saves getfenv(2) as the old environment, which should in theory be L
68 and setfenv(_M, 2) to set the tbale to be it's own environment
69 it does the package.loaded[test_c] thing for us
70 it returns the table it created, so we should just leave that on the stack as our result
71
72skang.thing() also uses getfenv(2) to grab the module's table
73 66
67 // In theory, the only thing on the stack now is 'test_c' from the require() call.
68
69// pseudo-indices, special tables that can be accessed like the stack -
70// LUA_GLOBALSINDEX - thread environment, where globals are
71// LUA_ENVIRONINDEX - C function environment, in this case luaopen_test_c() is the C function
72// LUA_REGISTRYINDEX - C registry, global, for unique keys use the module name as a string, or a lightuserdata address to a C object in our module.
73// lua_upvalueindex(n) - C function upvalues
74
75// The only locals we care about are skang and _M.
76// All modules go into package.loaded[name] as well.
77// skang is essentially a global anyway.
78// _M we pass back as the result, and our functions get added to it by skang.thing()
79// Not entirely true, skang.things is a proxy table, skang.things.ffunc.func would be our function.
80// skang.things.ffunc.module is our _M ('environment of our calling function', so that's the 'environment' right here, since we call skang.thing().
81// test_c.ffunc() -> test_c.__index(test_c, 'ffunc') -> skang.things[ffunc].value() -> test_c.c->ffunc()
82// this is a C function, not a Lua function
83
84// local skang = require 'skang'
85 lua_getglobal(L, "require");
86 lua_pushstring(L, "skang");
87 lua_call(L, 1, 1);
88 skang = lua_gettop(L);
89// dumpStack(L, skang);
90
91// local _M = skang.moduleBegin('test_c', nil, 'Copyright 2014 David Seikel', '0.1', '2014-03-27 03:57:00', nil, true)
92 lua_getfield(L, skang, "moduleBegin");
93 lua_pushstring(L, ourName);
94 lua_pushnil(L); // Author comes from copyright.
95 lua_pushstring(L, "Copyright 2014 David Seikel");
96 lua_pushstring(L, "0.1");
97 lua_pushstring(L, "2014-03-27 03:57:00");
98 lua_pushnil(L); // No skin.
99 lua_pushboolean(L, 0); // We are not a Lua module.
100 lua_call(L, 7, 1); // call 'skang.moduleBegin' with 7 arguments and 1 result.
101 _M = lua_gettop(L);
102// dumpStack(L, _M);
103
104 // At this point the stack should be - 'test_c', skang, _M. Let's test that.
105/*
106 int top = 0, i;
107
108 top = lua_gettop(L);
109 printf("MODULE test_c has %d stack items.\n", top);
110 for (i = 1; i <= top; i++)
111 dumpStack(L, i);
74*/ 112*/
75 113
76/* TODO - load skang, create things, etc. 114 // Save this module in the C registry.
77 115 lua_setfield(L, LUA_REGISTRYINDEX, ourName);
78local skang = require "skang" 116
79local _M = skang.moduleBegin("test_c", nil, "Copyright 2014 David Seikel", "0.1", "2014-03-27 03:57:00") 117// skang.thing('cfooble,c', 'Help text goes here', 1, 'number', \"'edit', 'The fooble:', 1, 1, 10, 50\", true)
118 lua_getfield(L, skang, "thing");
119 lua_pushstring(L, "cfooble,c");
120 lua_pushstring(L, "Help text");
121 lua_pushnumber(L, 1);
122 lua_pushstring(L, "number");
123 lua_pushstring(L, "'edit', 'The cfooble:', 1, 1, 10, 50");
124 lua_pushboolean(L, 1); // Is required.
125 lua_pushnil(L); // Default ACL.
126 lua_pushnil(L); // No boss.
127 lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment.
128 lua_call(L, 9, 0);
129
130// skang.thing('cbar', 'Help text', 'Default')
131 lua_getfield(L, skang, "thing");
132 lua_pushstring(L, "cbar");
133 lua_pushstring(L, "Help text");
134 lua_pushstring(L, "Default");
135 lua_pushnil(L); // No type.
136 lua_pushnil(L); // No widget.
137 lua_pushnil(L); // Not required.
138 lua_pushnil(L); // Default ACL.
139 lua_pushnil(L); // No boss.
140 lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment.
141 lua_call(L, 9, 0);
142
143// skang.thing('cfoo')
144 lua_getfield(L, skang, "thing");
145 lua_pushstring(L, "cfoo");
146 lua_pushnil(L); // No help.
147 lua_pushnil(L); // No default.
148 lua_pushnil(L); // No type.
149 lua_pushnil(L); // No widget.
150 lua_pushnil(L); // Not required.
151 lua_pushnil(L); // Default ACL.
152 lua_pushnil(L); // No boss.
153 lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment.
154 lua_call(L, 9, 0);
155
156// skang.thing('cfunc', 'Help Text', ffunc, 'number,string')
157 lua_getfield(L, skang, "thing");
158 lua_pushstring(L, "cfunc");
159 lua_pushstring(L, "cfunc does nothing really");
160 lua_pushcfunction(L, cfunc);
161 lua_pushstring(L, "number,string");
162 lua_pushnil(L); // No widget.
163 lua_pushnil(L); // Not required.
164 lua_pushnil(L); // Default ACL.
165 lua_pushnil(L); // No boss.
166 lua_getfield(L, LUA_REGISTRYINDEX, ourName); // Coz getfenv() can't find C environment.
167 lua_call(L, 9, 0);
168
169// skang.moduleEnd(_M)
170 lua_getfield(L, skang, "moduleEnd");
171 lua_getfield(L, LUA_REGISTRYINDEX, ourName);
172 lua_call(L, 1, 1);
80 173
81skang.thing("fooble,f", "Help text goes here", 1, "number", "'edit', 'The fooble:', 1, 1, 10, 50", true)
82skang.thing("bar", "Help text", "Default")
83skang.thing("foo")
84skang.thing("ffunc", "Help Text", ffunc, "number,string")
85
86skang.moduleEnd(_M)
87
88*/
89 return 1; 174 return 1;
90} 175}