diff --git a/CMakeLists.txt b/CMakeLists.txt index 6bdc261f78..ee8f63bf0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ topaz_add_library( src/tz/topaz.cpp src/tz/core/error.cpp src/tz/core/job.cpp + src/tz/core/lua.cpp src/tz/core/vector.cpp src/tz/core/matrix.cpp src/tz/core/quaternion.cpp diff --git a/include/tz/core/lua.hpp b/include/tz/core/lua.hpp new file mode 100644 index 0000000000..5a3780ede2 --- /dev/null +++ b/include/tz/core/lua.hpp @@ -0,0 +1,27 @@ +#ifndef TOPAZ_LUA_HPP +#define TOPAZ_LUA_HPP +#include "tz/core/error.hpp" +#include + +namespace tz +{ + /** + * @ingroup tz_core + * Attempt to execute a local lua file on the current thread. + * @param path Path to a local file containing lua code. + * + * @return @ref tz::error_code::precondition_failure If the provided path was invalid. + * @return @ref tz::error_code::unknown_error If the executed code caused an error. + */ + tz::error_code lua_execute_file(std::filesystem::path path); + /** + * @ingroup tz_core + * Attempt to execute some lua code on the current thread. + * @param lua_src String containing lua code to execute. + * + * @return @ref tz::error_code::unknown_error If the executed code caused an error. + */ + tz::error_code lua_execute(std::string_view lua_src); +} + +#endif // TOPAZ_LUA_HPP \ No newline at end of file diff --git a/include/tz/topaz.hpp b/include/tz/topaz.hpp index d327e8b350..244ab243c3 100644 --- a/include/tz/topaz.hpp +++ b/include/tz/topaz.hpp @@ -44,6 +44,8 @@ namespace tz { void job_system_initialise(); void job_system_terminate(); + void lua_initialise_local(); + void lua_initialise_all_threads(); } namespace gpu { diff --git a/src/tz/core/lua.cpp b/src/tz/core/lua.cpp new file mode 100644 index 0000000000..4e42bba7d7 --- /dev/null +++ b/src/tz/core/lua.cpp @@ -0,0 +1,67 @@ +#include "tz/core/lua.hpp" +#include "tz/topaz.hpp" + +#include "tz/core/job.hpp" + +extern "C" +{ +#include "lauxlib.h" +#include "lua.h" +#include "lualib.h" +} + +namespace tz +{ + thread_local lua_State* lua; + + namespace detail + { + void lua_initialise_local() + { + lua = luaL_newstate(); + luaL_openlibs(lua); + } + + void lua_initialise_all_threads() + { + std::vector jobs; + jobs.resize(tz::job_worker_count()); + for(std::size_t i = 0; i < jobs.size(); i++) + { + jobs[i] = tz::job_execute_on(lua_initialise_local, i); + } + lua_initialise_local(); + for(tz::job_handle job : jobs) + { + tz::job_wait(job); + } + } + } + + tz::error_code lua_execute_file(std::filesystem::path path) + { + if(!std::filesystem::exists(path)) + { + RETERR(tz::error_code::precondition_failure, "path to supposed lua file {} is invalid", path.string()); + } + luaL_dofile(lua, path.string().c_str()); + const char* err = lua_tostring(lua, -1); + if(err != nullptr) + { + RETERR(tz::error_code::unknown_error, "lua error while executing file {}: ", path.filename().string(), err); + } + return tz::error_code::success; + } + + tz::error_code lua_execute(std::string_view lua_src) + { + bool ret = luaL_dostring(lua, lua_src.data()) == false; + const char* err = lua_tostring(lua, -1); + if(!ret) + { + std::string code_snippet{lua_src.data(), lua_src.data() + std::min(20uz, lua_src.size())}; + RETERR(tz::error_code::unknown_error, "lua error while executing code \"{}...\": {}", code_snippet.c_str(), err != nullptr ? err : ""); + } + return tz::error_code::success; + } +} \ No newline at end of file diff --git a/src/tz/topaz.cpp b/src/tz/topaz.cpp index 74d4673a1e..f99b935349 100644 --- a/src/tz/topaz.cpp +++ b/src/tz/topaz.cpp @@ -5,6 +5,7 @@ namespace tz void initialise(appinfo info) { detail::job_system_initialise(); + detail::lua_initialise_all_threads(); os::initialise(); gpu::initialise(info); } diff --git a/test/tz/CMakeLists.txt b/test/tz/CMakeLists.txt index 8507f2e6b0..b71d081cb4 100644 --- a/test/tz/CMakeLists.txt +++ b/test/tz/CMakeLists.txt @@ -24,6 +24,12 @@ topaz_add_test( files/img.png ) +topaz_add_test( + TARGET tz_lua_execute_test + SOURCES + lua_execute_test.cpp +) + topaz_add_test( TARGET tz_vector_test SOURCES diff --git a/test/tz/lua_execute_test.cpp b/test/tz/lua_execute_test.cpp new file mode 100644 index 0000000000..1929d91205 --- /dev/null +++ b/test/tz/lua_execute_test.cpp @@ -0,0 +1,23 @@ +#include "tz/core/lua.hpp" +#include "tz/core/job.hpp" +#include "tz/topaz.hpp" + +int main() +{ + tz::initialise(); + // initialise topaz + + // run some lua code on main thread. + tz_must(tz::lua_execute("print(42069)")); + // set off a bunch of jobs which all run some lua code. + // dont care which workers end up doing it. + for(std::size_t i = 0; i < 69; i++) + { + tz::job_wait(tz::job_execute([]() + { + tz_must(tz::lua_execute("print(123)")); + })); + } + tz::terminate(); + return 0; +} \ No newline at end of file