| @@ -1,28 +1,6 @@ | |||
| #include "ScriptEngine.hpp" | |||
| #include <luajit-2.0/lua.hpp> | |||
| static const luaL_Reg lj_lib_load[] = { | |||
| { "", luaopen_base }, | |||
| { LUA_LOADLIBNAME, luaopen_package }, | |||
| { LUA_TABLIBNAME, luaopen_table }, | |||
| { LUA_STRLIBNAME, luaopen_string }, | |||
| { LUA_MATHLIBNAME, luaopen_math }, | |||
| { LUA_BITLIBNAME, luaopen_bit }, | |||
| { LUA_JITLIBNAME, luaopen_jit }, | |||
| { LUA_FFILIBNAME, luaopen_ffi }, | |||
| { NULL, NULL } | |||
| }; | |||
| LUALIB_API void custom_openlibs(lua_State *L) | |||
| { | |||
| const luaL_Reg *lib; | |||
| for (lib = lj_lib_load; lib->func; lib++) { | |||
| lua_pushcfunction(L, lib->func); | |||
| lua_pushstring(L, lib->name); | |||
| lua_call(L, 1, 0); | |||
| } | |||
| lua_pop(L, 1); | |||
| } | |||
| struct LuaJITEngine : ScriptEngine { | |||
| lua_State* L = NULL; | |||
| @@ -33,15 +11,15 @@ struct LuaJITEngine : ScriptEngine { | |||
| float sampleRate; | |||
| float sampleTime; | |||
| int bufferSize; | |||
| float* inputs[NUM_ROWS+1]; | |||
| float* outputs[NUM_ROWS+1]; | |||
| float* inputs[NUM_ROWS + 1]; | |||
| float* outputs[NUM_ROWS + 1]; | |||
| float* knobs; | |||
| bool* switches; | |||
| float* lights[NUM_ROWS+1]; | |||
| float* switchLights[NUM_ROWS+1]; | |||
| float* lights[NUM_ROWS + 1]; | |||
| float* switchLights[NUM_ROWS + 1]; | |||
| }; | |||
| LuaProcessBlock block; | |||
| LuaProcessBlock luaBlock; | |||
| ~LuaJITEngine() { | |||
| if (L) | |||
| @@ -53,22 +31,21 @@ struct LuaJITEngine : ScriptEngine { | |||
| } | |||
| int run(const std::string& path, const std::string& script) override { | |||
| ProcessBlock* original_block = getProcessBlock(); | |||
| block.sampleRate = original_block->sampleRate; | |||
| block.sampleTime = original_block->sampleTime; | |||
| block.bufferSize = original_block->bufferSize; | |||
| ProcessBlock* block = getProcessBlock(); | |||
| // Initialize all the pointers with an offset of -1 | |||
| block.knobs = (float*)&(original_block->knobs[-1]); | |||
| block.switches = (bool*)&(original_block->switches[-1]); | |||
| for(int i = 1; i < NUM_ROWS + 1; i++) { | |||
| block.inputs[i] = (float*)&(original_block->inputs[i-1][-1]); | |||
| block.outputs[i] = (float*)&(original_block->outputs[i-1][-1]); | |||
| block.lights[i] = (float*)&(original_block->lights[i-1][-1]); | |||
| block.switchLights[i] = (float*)&(original_block->switchLights[i-1][-1]); | |||
| #pragma GCC diagnostic push | |||
| #pragma GCC diagnostic ignored "-Warray-bounds" | |||
| luaBlock.knobs = &block->knobs[-1]; | |||
| luaBlock.switches = &block->switches[-1]; | |||
| for (int i = 0; i < NUM_ROWS; i++) { | |||
| luaBlock.inputs[i + 1] = &block->inputs[i][-1]; | |||
| luaBlock.outputs[i + 1] = &block->outputs[i][-1]; | |||
| luaBlock.lights[i + 1] = &block->lights[i][-1]; | |||
| luaBlock.switchLights[i + 1] = &block->switchLights[i][-1]; | |||
| } | |||
| #pragma GCC diagnostic pop | |||
| L = luaL_newstate(); | |||
| if (!L) { | |||
| @@ -77,7 +54,22 @@ struct LuaJITEngine : ScriptEngine { | |||
| } | |||
| // Import a subset of the standard library | |||
| custom_openlibs(L); | |||
| static const luaL_Reg lj_lib_load[] = { | |||
| {"", luaopen_base}, | |||
| {LUA_LOADLIBNAME, luaopen_package}, | |||
| {LUA_TABLIBNAME, luaopen_table}, | |||
| {LUA_STRLIBNAME, luaopen_string}, | |||
| {LUA_MATHLIBNAME, luaopen_math}, | |||
| {LUA_BITLIBNAME, luaopen_bit}, | |||
| {LUA_JITLIBNAME, luaopen_jit}, | |||
| {LUA_FFILIBNAME, luaopen_ffi}, | |||
| {NULL, NULL} | |||
| }; | |||
| for (const luaL_Reg* lib = lj_lib_load; lib->func; lib++) { | |||
| lua_pushcfunction(L, lib->func); | |||
| lua_pushstring(L, lib->name); | |||
| lua_call(L, 1, 0); | |||
| } | |||
| // Set user pointer | |||
| lua_pushlightuserdata(L, this); | |||
| @@ -102,11 +94,11 @@ struct LuaJITEngine : ScriptEngine { | |||
| } | |||
| lua_setglobal(L, "config"); | |||
| // Loads the FFI auxiliary functions. | |||
| // Load the FFI auxiliary functions. | |||
| std::stringstream ffi_stream; | |||
| ffi_stream | |||
| << "local ffi = require('ffi')" << std::endl | |||
| // Describes the struct 'LuaProcessBlock' that way LuaJIT knows how to access the data | |||
| // Describe the struct `LuaProcessBlock` so that LuaJIT knows how to access the data | |||
| << "ffi.cdef[[" << std::endl | |||
| << "struct LuaProcessBlock {" << std::endl | |||
| << "float sampleRate;" << std::endl | |||
| @@ -118,9 +110,9 @@ struct LuaJITEngine : ScriptEngine { | |||
| << "bool *switches;" << std::endl | |||
| << "float *lights[" << NUM_ROWS + 1 << "];" << std::endl | |||
| << "float *switchLights[" << NUM_ROWS + 1 << "];" << std::endl | |||
| <<"};]]" << std::endl | |||
| // Declares the function 'castBlock' used to transform the 'block' pointer into a LuaJIT cdata | |||
| << "function castBlock(b) return ffi.cast('struct LuaProcessBlock*', b) end"; | |||
| << "};]]" << std::endl | |||
| // Declare the function `_castBlock` used to transform `luaBlock` pointer into a LuaJIT cdata | |||
| << "function _castBlock(b) return ffi.cast('struct LuaProcessBlock*', b) end"; | |||
| std::string ffi_script = ffi_stream.str(); | |||
| // Compile the ffi script | |||
| @@ -183,21 +175,27 @@ struct LuaJITEngine : ScriptEngine { | |||
| } | |||
| // Create block object | |||
| lua_getglobal(L, "castBlock"); | |||
| lua_pushlightuserdata(L, (void *)&block); | |||
| if (lua_pcall(L, 1, 1, 0) != 0) | |||
| printf("error running function 'castBlock': %s", lua_tostring(L, -1)); | |||
| lua_getglobal(L, "_castBlock"); | |||
| lua_pushlightuserdata(L, (void*) &luaBlock); | |||
| if (lua_pcall(L, 1, 1, 0)) { | |||
| const char* s = lua_tostring(L, -1); | |||
| WARN("LuaJIT: Error casting block: %s", s); | |||
| display(s); | |||
| lua_pop(L, 1); | |||
| return -1; | |||
| } | |||
| return 0; | |||
| } | |||
| int process() override { | |||
| ProcessBlock* original_block = getProcessBlock(); | |||
| ProcessBlock* block = getProcessBlock(); | |||
| // Update the values of the block (the pointers should not change) | |||
| block.sampleRate = original_block->sampleRate; | |||
| block.sampleTime = original_block->sampleTime; | |||
| block.bufferSize = original_block->bufferSize; | |||
| // Update the values of the block. | |||
| // The pointer values do not change. | |||
| luaBlock.sampleRate = block->sampleRate; | |||
| luaBlock.sampleTime = block->sampleTime; | |||
| luaBlock.bufferSize = block->bufferSize; | |||
| // Duplicate process function | |||
| lua_pushvalue(L, -2); | |||