luavmstate.cpp 4.08 KB
Newer Older
1
2
3
4
5
#include "luavmstate.h"

#include <iostream>
#include "globalluatable.h"

6
7
#include "tgt/logmanager.h"

8
9
10
11
12
13
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}

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
static int lua_campvis_print(lua_State* L) {
    int nargs = lua_gettop(L);
    lua_getglobal(L, "tostring");
    std::string str;

    for (int i=1; i <= nargs; i++) {
        const char *s;
        size_t l;
        lua_pushvalue(L, -1);  /* function to be called */
        lua_pushvalue(L, i);   /* value to print */
        lua_call(L, 1, 1);
        s = lua_tolstring(L, -1, &l);  /* get result */
        if (s == NULL)
            return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print"));

        if (i>1) 
            str += "\t";
        str += s;
        lua_pop(L, 1);  /* pop result */
    }

    LINFOC("Lua", str);
    return 0;
}

static int lua_campvis_debug(lua_State* L) {
    for (;;) {
        char buffer[250];
        //luai_writestringerror("%s", "lua_debug> ");
        if (fgets(buffer, sizeof(buffer), stdin) == 0 || strcmp(buffer, "cont\n") == 0)
            return 0;
        if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || lua_pcall(L, 0, 0, 0))
            LDEBUGC("Lua", lua_tostring(L, -1));
        lua_settop(L, 0);  /* remove eventual returns */
    }
}

51
52
53

namespace campvis {

54
55
56
    LuaVmState::LuaVmState(bool loadStdLibs /*= true*/)
        : _luaState(0)
        , _luaStateMutex()
57
58
59
60
61
62
    {
        _luaState = luaL_newstate();

        // load standard Lua libraries
        if (loadStdLibs)
            luaL_openlibs(_luaState);
63
64
65
66
67
68
69
70
71

        /*
         * Store a pointer to the mutex guarding access to _luaState in the state's registry; this
         * way code that accesses Lua state directly (e.g. connections between sigslot's signals and
         * slots defined in Lua) has access to it and can lock it when necessary.
         */
        lua_pushlightuserdata(_luaState, static_cast<void*>(_luaState));
        lua_pushlightuserdata(_luaState, static_cast<void*>(&_luaStateMutex));
        lua_settable(_luaState, LUA_REGISTRYINDEX);
72
73
74
    }

    LuaVmState::~LuaVmState() {
75
        LuaStateMutexType::scoped_lock lock(_luaStateMutex);
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
        lua_close(_luaState);
    }

    void LuaVmState::logLuaError() {
        const char* errorMsg = lua_tostring(_luaState, -1);

        if (errorMsg == nullptr)
            std::cerr << "(error object is not a string)" << std::endl;
        else
            std::cerr << errorMsg << std::endl;

        lua_pop(_luaState, 1);
    }

    bool LuaVmState::execFile(const std::string& scriptPath) {
91
92
        LuaStateMutexType::scoped_lock lock(_luaStateMutex);

93
94
95
96
97
98
99
100
101
102
        // run a Lua script here; true is returned if there were errors
        if (luaL_dofile(_luaState, scriptPath.c_str())) {
            this->logLuaError();
            return false;
        }

        return true;
    }

    bool LuaVmState::execString(const std::string& scriptString) {
103
104
        LuaStateMutexType::scoped_lock lock(_luaStateMutex);

105
106
107
108
109
110
111
112
113
114
115
116
        if (luaL_dostring(_luaState, scriptString.c_str())) {
            this->logLuaError();
            return false;
        }

        return true;
    }

    std::shared_ptr<GlobalLuaTable> LuaVmState::getGlobalTable() {
        return std::shared_ptr<GlobalLuaTable>(new GlobalLuaTable(*this));
    }

117
    lua_State* LuaVmState::rawState() const {
118
119
120
        return _luaState;
    }

121
122
123
124
    LuaStateMutexType& LuaVmState::getMutex() {
        return _luaStateMutex;
    }

125
    void LuaVmState::callLuaFunc(int nargs, int nresults) {
126
127
        LuaStateMutexType::scoped_lock lock(_luaStateMutex);

128
129
130
131
        if (lua_pcall(_luaState, nargs, nresults, 0) != LUA_OK) {
            this->logLuaError();
        }
    }
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

    void LuaVmState::redirectLuaPrint() {
        LuaStateMutexType::scoped_lock lock(_luaStateMutex);

        static const struct luaL_Reg printlib[] = {
            {"print", &lua_campvis_print},
            {"debug", &lua_campvis_debug},
            {NULL, NULL} /* end of array */
        };

        lua_getglobal(_luaState, "_G");
        luaL_register(_luaState, NULL, printlib);
        lua_pop(_luaState, 1);
    }

147
}