-- BindingsProcessor.lua -- Implements additional processing that is done while generating the Lua bindings local access = {public = 0, protected = 1, private = 2} --- Defines classes that have a custom manual Push() implementation and should not generate the automatic one -- Map of classname -> true local g_HasCustomPushImplementation = { cEntity = true } function parser_hook(s) local container = classContainer.curr -- get the current container -- process access-specifying labels (public, private, etc) do local b, e, label = string.find(s, "^%s*(%w*)%s*:[^:]") -- we need to check for [^:], otherwise it would match 'namespace::type' if b then -- found a label, get the new access value from the global 'access' table if access[label] then container.curr_member_access = access[label] end -- else ? return strsub(s, e) -- normally we would use 'e+1', but we need to preserve the [^:] end end end --- Outputs the helper files supplementing the cLuaState class -- Writes: -- LuaState_Declaration.inc -- LuaState_Implementation.cpp -- LuaState_Typedefs.inc local function OutputLuaStateHelpers(a_Package) -- Collect all class types from ToLua: local types = {} for idx, item in ipairs(a_Package) do local mt = getmetatable(item) or {} if (mt.classtype == "class") then table.insert(types, {name = item.name, lname = item.lname}) end end table.sort(types, function(a_Item1, a_Item2) return (a_Item1.name:lower() < a_Item2.name:lower()) end ) -- Output the typedefs: do local f = assert(io.open("LuaState_Typedefs.inc", "w")) f:write("\n// LuaState_Typedefs.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n") f:write("// Provides a forward declaration and a typedef for a pointer to each class exported to the Lua API.\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do if not(item.name:match(".*<.*")) then -- Skip templates altogether -- Classes start with a "c", everything else is a struct: if (item.name:sub(1, 1) == "c") then f:write("class " .. item.name .. ";\n") else f:write("struct " .. item.name .. ";\n") end end end f:write("\n\n\n\n\n") for _, item in ipairs(types) do f:write("typedef " .. item.name .. " * Ptr" .. item.lname .. ";\n") end f:write("\n\n\n\n\n") f:close() end -- Output the Push() and GetStackValue() function declarations: do local f = assert(io.open("LuaState_Declaration.inc", "w")) f:write("\n// LuaState_Declaration.inc\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n") f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n") f:write("// This file expects to be included form inside the cLuaState class definition\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do f:write("void Push(" .. item.name .. " * a_Value);\n") end for _, item in ipairs(types) do f:write("void GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal);\n") end f:write("\n\n\n\n\n") f:close() end -- Output the Push() and GetStackValue() function implementations: do local f = assert(io.open("LuaState_Implementation.cpp", "w")) f:write("\n// LuaState_Implementation.cpp\n\n// This file is generated along with the Lua bindings by ToLua. Do not edit manually, do not commit to repo.\n") f:write("// Implements a Push() and GetStackValue() function for each class exported to the Lua API.\n") f:write("// This file expects to be compiled as a separate translation unit\n") f:write("\n\n\n\n\n") f:write("#include \"Globals.h\"\n#include \"LuaState.h\"\n#include \"tolua++/include/tolua++.h\"\n") f:write("\n\n\n\n\n") for _, item in ipairs(types) do if not(g_HasCustomPushImplementation[item.name]) then f:write("void cLuaState::Push(" .. item.name .. " * a_Value)\n{\n\tASSERT(IsValid());\n") f:write("\ttolua_pushusertype(m_LuaState, a_Value, \"" .. item.name .. "\");\n"); f:write("\tm_NumCurrentFunctionArgs += 1;\n") f:write("}\n\n\n\n\n\n") end end for _, item in ipairs(types) do f:write("void cLuaState::GetStackValue(int a_StackPos, Ptr" .. item.lname .. " & a_ReturnedVal)\n{\n\tASSERT(IsValid());\n") f:write("\tif (lua_isnil(m_LuaState, a_StackPos))\n\t{\n") f:write("\t a_ReturnedVal = nullptr;\n") f:write("\t return;\n\t}\n") f:write("\ttolua_Error err;\n") f:write("\tif (tolua_isusertype(m_LuaState, a_StackPos, \"" .. item.name .. "\", false, &err))\n") f:write("\t{\n") f:write("\t a_ReturnedVal = *(reinterpret_cast<" .. item.name .. " **>(lua_touserdata(m_LuaState, a_StackPos)));\n") f:write("\t}\n") f:write("}\n\n\n\n\n\n") end f:close() end end function pre_output_hook(a_Package) OutputLuaStateHelpers(a_Package) end function post_output_hook() print("Bindings have been generated.") end