-
Notifications
You must be signed in to change notification settings - Fork 0
/
lua_ex.cpp
164 lines (129 loc) · 3.8 KB
/
lua_ex.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// lua_ex.c - How to embed LUA library into C/C++ - example
// EXIT_* constants
#include <stdlib.h>
// printf(3)....
#include <stdio.h>
// variable errno
#include <errno.h>
// strerror(3)
#include <string.h>
// uname(2)
#include <sys/utsname.h>
// sysinfo(2) - uptime
#include <sys/sysinfo.h>
// NOTE: C++ must use "lua.hpp", however C must use "lua.h"
#include <lua.hpp>
#define LOCAL_VALIDATE_LUA_STACK \
if ( lua_gettop(ls) ){ \
fprintf(stderr, "LUA has unbalanced stack before lua_close() call: %d <> %d", \
lua_gettop(ls), 0); \
return EXIT_FAILURE; \
}
static int l_uname_machine(lua_State *ls){
struct utsname un;
if (uname(&un)){
char msg[256];
snprintf(msg, sizeof(msg), "Error calling uname(): %s",
strerror(errno));
// reporting error: insert NIL and Error message
lua_pushnil(ls);
lua_pushstring(ls, msg);
return 2; // number of results
} else {
lua_pushstring(ls, un.machine);
return 1; // number of results
}
}
static int l_uptime_seconds(lua_State *ls){
struct sysinfo in;
if (sysinfo(&in)){
char msg[256];
snprintf(msg, sizeof(msg), "Error calling sysinfo(): %s",
strerror(errno));
// reporting error: insert NIL and Error message
lua_pushnil(ls);
lua_pushstring(ls, msg);
return 2; // number of results
} else {
// according to https://stackoverflow.com/a/4079267
// sizeof() can't be used in C++ preprocessor
if ( sizeof(in.uptime) > sizeof(lua_Integer) ){
// lua_Number is typically double
lua_pushnumber(ls, (lua_Number) in.uptime);
} else {
lua_pushinteger(ls, (lua_Integer) in.uptime);
}
return 1; // number of results
}
}
static int Ex_ExtendLUA(lua_State *ls){
lua_pushcfunction(ls, l_uptime_seconds);
lua_setglobal(ls, "uptime_seconds");
LOCAL_VALIDATE_LUA_STACK;
lua_pushcfunction(ls, l_uname_machine);
lua_setglobal(ls, "uname_machine");
LOCAL_VALIDATE_LUA_STACK;
return EXIT_SUCCESS;
}
// reports error on LUA call and show error message from stack.
// also pops-out error message from stack.
static int Ex_ReportLuaError(lua_State *ls, const char *fn){
fprintf(stderr, "Error calling %s(): %s", fn, lua_tostring(ls, -1));
lua_pop(ls, 1); /* pops LUA error message from the stack */
return EXIT_FAILURE;
}
// runs LUA commands in luaCommands, returns EXIT_SUCESS or EXIT_FAILURE
// this call always uses fresh LUA instance
static int Ex_RunLua(const char *luaCommands){
int rc = EXIT_FAILURE; // our return value
int err = 0; // for errors from LUA calls
lua_State *ls = luaL_newstate();
if ( ls == NULL ){
fprintf(stderr,"luaL_newstate() returned NULL\n");
goto exit0;
}
luaL_openlibs(ls);
if (Ex_ExtendLUA(ls)){
goto exit1;
}
err = luaL_loadstring(ls, luaCommands);
if (err){
Ex_ReportLuaError(ls, "luaL_loadstring");
goto exit1;
}
// now there is "luaCommmands" string on LUA stack (!)
// Verify that it is true.
if (lua_gettop(ls)!=1){
fprintf(stderr, "Invalid LUA stack - got %d, expected %d\n", 1, 0);
goto exit1;
}
// this executes our commands
err = lua_pcall(ls, 0, 0, 0);
if (err){
fprintf(stderr, "This LUA command failed:\n%s\n", luaCommands);
Ex_ReportLuaError(ls, "lua_pcall");
goto exit1;
}
rc = EXIT_SUCCESS;
exit1:
// additionally report unbalanced stack
if ( lua_gettop(ls) ){
fprintf(stderr, "LUA has unbalanced stack before lua_close() call: %d <> %d",
lua_gettop(ls), 0);
rc = EXIT_FAILURE;
}
lua_close(ls);
exit0:
return rc;
}
int main(int argc, char **argv)
{
int rc = EXIT_SUCCESS;
// NOTE: unlike TCL there is no global Init function
rc = Ex_RunLua("print('Hello, world on ' .. uname_machine() .. '!')");
if (rc == EXIT_SUCCESS){
rc = Ex_RunLua("print('System uptime is ', uptime_seconds() ,' seconds.')");
}
// NOTE: unlike TCL there is no global Finalize function
return rc;
}