Function dumping using C API (#49)
This commit is contained in:
parent
7947d7af17
commit
265b12370b
@ -2,6 +2,51 @@
|
||||
|
||||
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) {
|
||||
using namespace std::chrono;
|
||||
|
||||
|
||||
@ -6,27 +6,8 @@
|
||||
|
||||
namespace effil {
|
||||
|
||||
// TODO: make function more reliable
|
||||
// string.dump can be changed by user
|
||||
// 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::string dumpFunction(const sol::function& f);
|
||||
sol::function loadString(const sol::state_view& lua, const std::string& str);
|
||||
std::chrono::milliseconds fromLuaTime(int duration, const sol::optional<std::string>& period);
|
||||
|
||||
typedef std::vector<effil::StoredObject> StoredArray;
|
||||
|
||||
@ -50,10 +50,7 @@ public:
|
||||
template <typename SolObject>
|
||||
FunctionHolder(SolObject luaObject) noexcept {
|
||||
sol::state_view lua(luaObject.lua_state());
|
||||
sol::function dumper = lua["string"]["dump"];
|
||||
if (!dumper.valid())
|
||||
throw Exception() << "Invalid string.dump()";
|
||||
function_ = dumper(luaObject);
|
||||
function_ = dumpFunction(luaObject);
|
||||
}
|
||||
|
||||
bool rawCompare(const BaseHolder* other) const noexcept final {
|
||||
@ -61,10 +58,7 @@ public:
|
||||
}
|
||||
|
||||
sol::object unpack(sol::this_state state) const final {
|
||||
sol::state_view lua((lua_State*)state);
|
||||
sol::function loader = lua["loadstring"];
|
||||
REQUIRE(loader.valid()) << "Invalid loadstring()";
|
||||
sol::function result = loader(function_);
|
||||
sol::function result = loadString(state, function_);
|
||||
// The result of restaring always is valid function.
|
||||
assert(result.valid());
|
||||
return sol::make_object(state, result);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user