Compare commits
No commits in common. "17cf627cb9febff8ab7076f26d6909350f4fc3f1" and "763bb230a747f984a9bbbe4bc4e3f31fe4365ee8" have entirely different histories.
17cf627cb9
...
763bb230a7
4 changed files with 30 additions and 43 deletions
|
@ -7,9 +7,6 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
extern const char* WRAPPER_SRC; // TODO: Move this to a shared header
|
|
||||||
int script_errhandler(lua_State*); // extern
|
|
||||||
|
|
||||||
SignalSource::SignalSource() : std::shared_ptr<Signal>(std::make_shared<Signal>()) {}
|
SignalSource::SignalSource() : std::shared_ptr<Signal>(std::make_shared<Signal>()) {}
|
||||||
SignalSource::~SignalSource() = default;
|
SignalSource::~SignalSource() = default;
|
||||||
|
|
||||||
|
@ -25,13 +22,16 @@ LuaSignalConnection::LuaSignalConnection(lua_State* L, std::weak_ptr<Signal> par
|
||||||
|
|
||||||
// https://stackoverflow.com/a/31952046/16255372
|
// https://stackoverflow.com/a/31952046/16255372
|
||||||
|
|
||||||
// Save function so it doesn't get GC'd
|
// Save function and current thread so they don't get GC'd
|
||||||
function = luaL_ref(L, LUA_REGISTRYINDEX);
|
function = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
lua_pushthread(L);
|
||||||
|
thread = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaSignalConnection::~LuaSignalConnection() {
|
LuaSignalConnection::~LuaSignalConnection() {
|
||||||
// Remove LuaSignalConnectionthread so that it can get properly GC'd
|
// Remove LuaSignalConnectionthread so that it can get properly GC'd
|
||||||
luaL_unref(state, LUA_REGISTRYINDEX, function);
|
luaL_unref(state, LUA_REGISTRYINDEX, function);
|
||||||
|
luaL_unref(state, LUA_REGISTRYINDEX, thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -56,21 +56,18 @@ static void stackdump(lua_State* L) {
|
||||||
void LuaSignalConnection::Call(std::vector<Variant> args) {
|
void LuaSignalConnection::Call(std::vector<Variant> args) {
|
||||||
lua_State* thread = lua_newthread(state);
|
lua_State* thread = lua_newthread(state);
|
||||||
|
|
||||||
// Push wrapepr as thread function
|
// Push function
|
||||||
luaL_loadbuffer(thread, WRAPPER_SRC, strlen(WRAPPER_SRC), "=PCALL_WRAPPER");
|
|
||||||
|
|
||||||
// Push function as upvalue for wrapper
|
|
||||||
lua_rawgeti(thread, LUA_REGISTRYINDEX, function);
|
lua_rawgeti(thread, LUA_REGISTRYINDEX, function);
|
||||||
|
|
||||||
// Also push our error handler and generate wrapped function
|
|
||||||
lua_pushcfunction(thread, script_errhandler);
|
|
||||||
lua_call(thread, 2, 1);
|
|
||||||
|
|
||||||
for (Variant arg : args) {
|
for (Variant arg : args) {
|
||||||
arg.PushLuaValue(thread);
|
arg.PushLuaValue(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_resume(thread, args.size());
|
int status = lua_resume(thread, args.size());
|
||||||
|
if (status > LUA_YIELD) {
|
||||||
|
Logger::error(lua_tostring(thread, -1));
|
||||||
|
lua_pop(thread, 1); // Pop return value
|
||||||
|
}
|
||||||
|
|
||||||
lua_pop(state, 1); // Pop thread
|
lua_pop(state, 1); // Pop thread
|
||||||
}
|
}
|
||||||
|
@ -155,7 +152,11 @@ void Signal::Fire(std::vector<Variant> args) {
|
||||||
arg.PushLuaValue(thread);
|
arg.PushLuaValue(thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_resume(thread, args.size());
|
int status = lua_resume(thread, args.size());
|
||||||
|
if (status > LUA_YIELD) {
|
||||||
|
Logger::error(lua_tostring(thread, -1));
|
||||||
|
lua_pop(thread, 1); // Pop return value
|
||||||
|
}
|
||||||
|
|
||||||
// Remove thread from registry
|
// Remove thread from registry
|
||||||
luaL_unref(thread, LUA_REGISTRYINDEX, threadId);
|
luaL_unref(thread, LUA_REGISTRYINDEX, threadId);
|
||||||
|
|
|
@ -45,7 +45,7 @@ public:
|
||||||
|
|
||||||
class LuaSignalConnection : public SignalConnection {
|
class LuaSignalConnection : public SignalConnection {
|
||||||
lua_State* state;
|
lua_State* state;
|
||||||
int function;
|
int function, thread;
|
||||||
|
|
||||||
friend Signal;
|
friend Signal;
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "lauxlib.h"
|
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
#include "objects/base/member.h"
|
#include "objects/base/member.h"
|
||||||
|
@ -14,11 +13,9 @@
|
||||||
|
|
||||||
int script_wait(lua_State*);
|
int script_wait(lua_State*);
|
||||||
int script_delay(lua_State*);
|
int script_delay(lua_State*);
|
||||||
|
int script_wrapper(lua_State*);
|
||||||
int script_errhandler(lua_State*);
|
int script_errhandler(lua_State*);
|
||||||
|
|
||||||
// TODO: Move this to a shared header
|
|
||||||
const char* WRAPPER_SRC = "local func, errhandler = ... return function(...) local args = {...} xpcall(function() func(unpack(args)) end, errhandler) end";
|
|
||||||
|
|
||||||
Script::Script(): Instance(&TYPE) {
|
Script::Script(): Instance(&TYPE) {
|
||||||
source = "print(\"Hello, world!\")";
|
source = "print(\"Hello, world!\")";
|
||||||
}
|
}
|
||||||
|
@ -30,7 +27,6 @@ void Script::Run() {
|
||||||
std::shared_ptr<ScriptContext> scriptContext = dataModel().value()->GetService<ScriptContext>();
|
std::shared_ptr<ScriptContext> scriptContext = dataModel().value()->GetService<ScriptContext>();
|
||||||
|
|
||||||
lua_State* L = scriptContext->state;
|
lua_State* L = scriptContext->state;
|
||||||
int top = lua_gettop(L);
|
|
||||||
|
|
||||||
// Create thread
|
// Create thread
|
||||||
this->thread = lua_newthread(L);
|
this->thread = lua_newthread(L);
|
||||||
|
@ -58,28 +54,13 @@ void Script::Run() {
|
||||||
|
|
||||||
lua_pop(Lt, 1); // _G
|
lua_pop(Lt, 1); // _G
|
||||||
|
|
||||||
// Push wrapper as thread function
|
// Load source and push onto thread stack as upvalue for wrapper closure
|
||||||
luaL_loadbuffer(Lt, WRAPPER_SRC, strlen(WRAPPER_SRC), "=PCALL_WRAPPER");
|
luaL_loadbuffer(Lt, source.c_str(), source.size(), this->GetFullName().c_str());
|
||||||
|
lua_pushcclosure(Lt, script_wrapper, 1);
|
||||||
|
|
||||||
// Load source code and push onto thread as upvalue for wrapper
|
|
||||||
int status = luaL_loadbuffer(Lt, source.c_str(), source.size(), this->GetFullName().c_str());
|
|
||||||
if (status != LUA_OK) {
|
|
||||||
// Failed to parse/load chunk
|
|
||||||
Logger::error(lua_tostring(Lt, -1));
|
|
||||||
|
|
||||||
lua_settop(L, top);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push our error handler and then generate the wrapped function
|
|
||||||
lua_pushcfunction(Lt, script_errhandler);
|
|
||||||
lua_call(Lt, 2, 1);
|
|
||||||
|
|
||||||
// Resume the thread
|
|
||||||
lua_resume(Lt, 0);
|
lua_resume(Lt, 0);
|
||||||
|
|
||||||
lua_pop(L, 1); // Pop the thread
|
lua_pop(L, 1); // Pop the thread
|
||||||
lua_settop(L, top);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Script::Stop() {
|
void Script::Stop() {
|
||||||
|
@ -115,6 +96,13 @@ int script_delay(lua_State* L) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int script_wrapper(lua_State* L) {
|
||||||
|
lua_pushcfunction(L, script_errhandler);
|
||||||
|
lua_pushvalue(L, lua_upvalueindex(1));
|
||||||
|
lua_pcall(L, 0, 0, -2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int script_errhandler(lua_State* L) {
|
int script_errhandler(lua_State* L) {
|
||||||
std::string errorMessage = lua_tostring(L, -1);
|
std::string errorMessage = lua_tostring(L, -1);
|
||||||
Logger::error(errorMessage);
|
Logger::error(errorMessage);
|
||||||
|
@ -127,9 +115,8 @@ int script_errhandler(lua_State* L) {
|
||||||
int stack = 1;
|
int stack = 1;
|
||||||
while (lua_getstack(L, stack++, &dbg)) {
|
while (lua_getstack(L, stack++, &dbg)) {
|
||||||
lua_getinfo(L, "nlSu", &dbg);
|
lua_getinfo(L, "nlSu", &dbg);
|
||||||
// Ignore C frames and internal wrappers
|
if (strcmp(dbg.what, "C") == 0)
|
||||||
if (strcmp(dbg.what, "C") == 0 || strcmp(dbg.source, "=PCALL_WRAPPER") == 0)
|
continue; // Ignore C frames
|
||||||
continue;
|
|
||||||
|
|
||||||
Logger::trace(dbg.source, dbg.currentline);
|
Logger::trace(dbg.source, dbg.currentline);
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,8 +151,7 @@ ScriptDocument::ScriptDocument(std::shared_ptr<Script> script, QWidget* parent):
|
||||||
scintilla->setCaretForegroundColor(palette().text().color());
|
scintilla->setCaretForegroundColor(palette().text().color());
|
||||||
scintilla->setFont(font);
|
scintilla->setFont(font);
|
||||||
scintilla->setTabWidth(4);
|
scintilla->setTabWidth(4);
|
||||||
scintilla->setEolMode(QsciScintilla::EolUnix); // LF endings
|
|
||||||
|
|
||||||
scintilla->setText(QString::fromStdString(script->source));
|
scintilla->setText(QString::fromStdString(script->source));
|
||||||
|
|
||||||
ObLuaLexer* lexer = new ObLuaLexer;
|
ObLuaLexer* lexer = new ObLuaLexer;
|
||||||
|
|
Loading…
Add table
Reference in a new issue