Function dumping using C API (#49)
This commit is contained in:
parent
7947d7af17
commit
265b12370b
@ -2,6 +2,51 @@
|
|||||||
|
|
||||||
namespace effil {
|
namespace effil {
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string luaError(int errCode)
|
||||||
|
{
|
||||||
|
switch(errCode)
|
||||||
|
{
|
||||||
|
case LUA_ERRSYNTAX: return "Invalid syntax (LUA_ERRSYNTAX)";
|
||||||
|
case LUA_ERRMEM: return "Memory allocation error (LUA_ERRMEM)";
|
||||||
|
case LUA_ERRRUN: return "Execution error (LUA_ERRRUN)";
|
||||||
|
case LUA_ERRGCMM: return "Error in __gc method (LUA_ERRGCMM)";
|
||||||
|
case LUA_ERRERR: return "Recursive error (LUA_ERRERR)";
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dumpMemoryWriter(lua_State*, const void* batch, size_t batchSize, void* storage) {
|
||||||
|
if (storage == nullptr || batch == nullptr)
|
||||||
|
return 1;
|
||||||
|
if (batchSize) {
|
||||||
|
std::string& buff = *reinterpret_cast<std::string*>(storage);
|
||||||
|
const char* newData = reinterpret_cast<const char*>(batch);
|
||||||
|
buff.insert(buff.end(), newData, newData + batchSize);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dumpFunction(const sol::function& f) {
|
||||||
|
sol::state_view lua(f.lua_state());
|
||||||
|
sol::stack::push(lua, f);
|
||||||
|
std::string result;
|
||||||
|
int ret = lua_dump(lua, dumpMemoryWriter, &result);
|
||||||
|
REQUIRE(ret == LUA_OK) << "Unable to dump Lua function: " << luaError(ret);
|
||||||
|
sol::stack::remove(lua, -1, 1);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
sol::function loadString(const sol::state_view& lua, const std::string& str) {
|
||||||
|
int ret = luaL_loadbuffer(lua, str.c_str(), str.size(), nullptr);
|
||||||
|
REQUIRE(ret == LUA_OK) << "Unable to load function from string: " << luaError(ret);
|
||||||
|
return sol::stack::pop<sol::function>(lua);
|
||||||
|
}
|
||||||
|
|
||||||
std::chrono::milliseconds fromLuaTime(int duration, const sol::optional<std::string>& period) {
|
std::chrono::milliseconds fromLuaTime(int duration, const sol::optional<std::string>& period) {
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
|||||||
@ -6,27 +6,8 @@
|
|||||||
|
|
||||||
namespace effil {
|
namespace effil {
|
||||||
|
|
||||||
// TODO: make function more reliable
|
std::string dumpFunction(const sol::function& f);
|
||||||
// string.dump can be changed by user
|
sol::function loadString(const sol::state_view& lua, const std::string& str);
|
||||||
// TODO: Add cache for each state
|
|
||||||
inline std::string dumpFunction(const sol::function& f) {
|
|
||||||
sol::state_view lua(f.lua_state());
|
|
||||||
sol::function dumper = lua["string"]["dump"];
|
|
||||||
REQUIRE(dumper.valid() && dumper.get_type() == sol::type::function)
|
|
||||||
<< "Invalid string.dump() in state";
|
|
||||||
return dumper(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: make function more reliable
|
|
||||||
// loadstring can be changed by user
|
|
||||||
// TODO: Add cache for each state
|
|
||||||
inline sol::function loadString(const sol::state_view& lua, const std::string& str) {
|
|
||||||
sol::function loader = lua["loadstring"];
|
|
||||||
REQUIRE(loader.valid() && loader.get_type() == sol::type::function)
|
|
||||||
<< "Invalid loadstring function";
|
|
||||||
return loader(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::milliseconds fromLuaTime(int duration, const sol::optional<std::string>& period);
|
std::chrono::milliseconds fromLuaTime(int duration, const sol::optional<std::string>& period);
|
||||||
|
|
||||||
typedef std::vector<effil::StoredObject> StoredArray;
|
typedef std::vector<effil::StoredObject> StoredArray;
|
||||||
|
|||||||
@ -50,10 +50,7 @@ public:
|
|||||||
template <typename SolObject>
|
template <typename SolObject>
|
||||||
FunctionHolder(SolObject luaObject) noexcept {
|
FunctionHolder(SolObject luaObject) noexcept {
|
||||||
sol::state_view lua(luaObject.lua_state());
|
sol::state_view lua(luaObject.lua_state());
|
||||||
sol::function dumper = lua["string"]["dump"];
|
function_ = dumpFunction(luaObject);
|
||||||
if (!dumper.valid())
|
|
||||||
throw Exception() << "Invalid string.dump()";
|
|
||||||
function_ = dumper(luaObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rawCompare(const BaseHolder* other) const noexcept final {
|
bool rawCompare(const BaseHolder* other) const noexcept final {
|
||||||
@ -61,10 +58,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
sol::object unpack(sol::this_state state) const final {
|
sol::object unpack(sol::this_state state) const final {
|
||||||
sol::state_view lua((lua_State*)state);
|
sol::function result = loadString(state, function_);
|
||||||
sol::function loader = lua["loadstring"];
|
|
||||||
REQUIRE(loader.valid()) << "Invalid loadstring()";
|
|
||||||
sol::function result = loader(function_);
|
|
||||||
// The result of restaring always is valid function.
|
// The result of restaring always is valid function.
|
||||||
assert(result.valid());
|
assert(result.valid());
|
||||||
return sol::make_object(state, result);
|
return sol::make_object(state, result);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user