139 lines
3.5 KiB
C++

#include <iostream>
#include <string>
extern "C" {
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <luasocket.h>
#ifndef PRELOAD
#include <oilbit.h>
#else
#include <oilall.h>
#endif
}
#include "hello.hpp"
////////////////////////////////////////////////////////////////////////////////
static bool callfield(lua_State *L, const char *name, int narg, int nres);
static void pushfield(lua_State *L, const char *name);
lua_State *newstate()
{
lua_State *L = lua_open();
luaL_openlibs(L);
luaopen_socket_core(L);
#ifndef PRELOAD
luaopen_oil_bit(L); // open the OiL bit library (only OiL C library)
#else
luapreload_oilall(L); // preload all OiL libraries
#endif
return L;
}
int main(int argc, char* argv[])
{
// legacy C++ object and wrapper that translates Hello methods into Lua methods
Hello::HelloWorld *hello = new Hello::HelloWorld(true);
Hello::Wrapper *wrappedHello = new Hello::Wrapper(hello);
lua_State *L = newstate();
// Lua wrapper class of 'Hello' class and Lua wrapper of 'hello' object
Hello::Exported *exportedClass = new Hello::Exported(L);
Hello::Exported::Object *exportedHello = exportedClass->newObject(wrappedHello);
// require "oil"
lua_pushliteral(L, "oil");
callfield(L, "require", 1, 0);
// oil.loadidl("interface Hello { ... }")
lua_pushliteral(L,
"interface Hello {"
" attribute boolean quiet;"
" readonly attribute long count;"
" string say_hello_to(in string name);"
"};");
callfield(L, "oil.loadidl", 1, 0);
// oil.writeto('...ref', oil.tostring(oil.newservant(<hello>, "::Hello")))
lua_pushliteral(L, "../hello/ref.ior");
exportedHello->pushOnStack();
lua_pushliteral(L, "::Hello");
callfield(L, "oil.newservant", 2, 1);
callfield(L, "oil.tostring", 1, 1);
callfield(L, "oil.writeto", 2, 0);
// oil.main(oil.run())
pushfield(L, "oil.run");
callfield(L, "oil.main", 1, 0);
return 0;
}
////////////////////////////////////////////////////////////////////////////////
static void pushfield(lua_State *L, const char *name)
{
const char *end = strchr(name, '.');
lua_pushvalue(L, LUA_GLOBALSINDEX);
while (end) {
lua_pushlstring(L, name, end - name);
lua_gettable(L, -2);
lua_remove(L, -2);
if (lua_isnil(L, -1)) return;
name = end+1;
end = strchr(name, '.');
}
lua_pushstring(L, name);
lua_gettable(L, -2);
lua_remove(L, -2);
}
static int traceback (lua_State *L) {
lua_getfield(L, LUA_GLOBALSINDEX, "debug");
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
return 1;
}
lua_getfield(L, -1, "traceback");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 2);
return 1;
}
lua_pushvalue(L, 1); /* pass error message */
lua_pushinteger(L, 2); /* skip this function and traceback */
lua_call(L, 2, 1); /* call debug.traceback */
return 1;
}
static bool callfield(lua_State *L, const char *name, int narg, int nres)
{
pushfield(L, name);
int base = lua_gettop(L) - narg; /* 1st arg index */
lua_insert(L, base); /* put function under args */
lua_pushcfunction(L, traceback); /* push traceback function */
lua_insert(L, base); /* put traceback under function and args */
int status = lua_pcall(L, narg, nres, base);
lua_remove(L, base); /* remove traceback function */
if (status && !lua_isnil(L, -1)) {
const char *msg;
if (lua_istable(L, -1)) {
lua_getfield(L, LUA_GLOBALSINDEX, "tostring");
lua_insert(L, -2);
lua_call(L, 1, 1);
}
msg = lua_tostring(L, -1);
if (msg == NULL) msg = "(error object is not a string)";
fprintf(stderr, "%s\n", msg);
lua_pop(L, 1);
return false;
}
return true;
}