{"id":21861330,"url":"https://github.com/seng3694/cluamoduleexample","last_synced_at":"2025-03-21T20:18:36.488Z","repository":{"id":114139370,"uuid":"161383533","full_name":"Seng3694/CLuaModuleExample","owner":"Seng3694","description":"Example for creating a Lua module in C","archived":false,"fork":false,"pushed_at":"2018-12-11T20:45:00.000Z","size":4,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-26T14:50:18.042Z","etag":null,"topics":["c","cmake","example","lua","lua-module"],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Seng3694.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-12-11T19:30:12.000Z","updated_at":"2024-07-29T14:11:56.000Z","dependencies_parsed_at":"2023-06-14T07:00:35.392Z","dependency_job_id":null,"html_url":"https://github.com/Seng3694/CLuaModuleExample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seng3694%2FCLuaModuleExample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seng3694%2FCLuaModuleExample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seng3694%2FCLuaModuleExample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Seng3694%2FCLuaModuleExample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Seng3694","download_url":"https://codeload.github.com/Seng3694/CLuaModuleExample/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244860600,"owners_count":20522466,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","cmake","example","lua","lua-module"],"created_at":"2024-11-28T03:11:12.920Z","updated_at":"2025-03-21T20:18:36.460Z","avatar_url":"https://github.com/Seng3694.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Example for creating a Lua module in C #\n\nLet's assume we want to create an unnecessary `custommath` module for Lua.\n\n## Goal ##\n\n```lua\nlocal custommath = require \"custommath\"\n\nprint(custommath.add(10, 20))\n```\n\n## How to reach our goal? ##\n\n```C\n#ifndef CUSTOM_MATH_H\n#define CUSTOM_MATH_H\n\n//c++ compatability\n#ifdef __cplusplus\n#define C_API_BEGIN extern \"C\" {\n#define C_API_END }\n#else\n#define C_API_BEGIN\n#define C_API_END\n#endif // !__cplusplus\n\nC_API_BEGIN\n\n#include \u003clua.h\u003e\n#include \u003clualib.h\u003e\n#include \u003clauxlib.h\u003e\n#include \u003cmath.h\u003e\n\n//the functions we want to implement. names do not matter\nint add(lua_State* lua);\nint subtract(lua_State* lua);\nint multiply(lua_State* lua);\nint divide(lua_State* lua);\n\n//the function which will be called when \"require \"custommath\"\" is called from lua\nint __declspec(dllexport) luaopen_custommath(lua_State* lua);\n\nC_API_END\n\n#endif // !CUSTOM_MATH_H\n\n```\n\nThe key part in this header file is this function:\n```C\nint __declspec(dllexport) luaopen_custommath(lua_State* lua);\n```\n\nFirst of all you need the `_declspec(dllexport)` because we want to create a shared library.\nIt is also required to have this specific signature `int luaopen[MODULE](lua_State*)` so Lua can find the function. In our case `[MODULE]` is `custommath`.\n\n**Note**: The shared library has to have the same name as the module. In this case `custommath`.\n\nI won't go into implementation details of the actual math functions. These are just basic Lua stack manipulations. If you are struggling with these please read the manual.\n\nThe `int luaopen_custommath(lua_State*)` implementation:\n\n```C\nint luaopen_custommath(lua_State* lua)\n{\n    //create table with 4 entries\n    lua_createtable(lua, 0, 4);\n\n    //set key value pairs of the table\n    lua_pushstring(lua, \"add\");\n    lua_pushcfunction(lua, \u0026add);\n    lua_settable(lua, -3);\n\n    lua_pushstring(lua, \"subtract\");\n    lua_pushcfunction(lua, \u0026subtract);\n    lua_settable(lua, -3);\n\n    lua_pushstring(lua, \"multiply\");\n    lua_pushcfunction(lua, \u0026multiply);\n    lua_settable(lua, -3);\n\n    lua_pushstring(lua, \"divide\");\n    lua_pushcfunction(lua, \u0026divide);\n    lua_settable(lua, -3);\n\n    //there should now be a table on the stack with our 4 functions\n    return 1;\n}\n```\n\nRunning the following Lua script:\n\n```lua\nlocal custommath = require \"custommath\"\n\nlocal a = 1.1\nlocal b = 2.2\n\nprint(tostring(a) .. \" + \" .. tostring(b) .. \" = \" .. tostring(custommath.add(a, b)))\nprint(tostring(a) .. \" - \" .. tostring(b) .. \" = \" .. tostring(custommath.subtract(a, b)))\nprint(tostring(a) .. \" * \" .. tostring(b) .. \" = \" .. tostring(custommath.multiply(a, b)))\nprint(tostring(a) .. \" / \" .. tostring(b) .. \" = \" .. tostring(custommath.divide(a, b)))\n\n```\n\nwill result in following output:\n```\n1.1 + 2.2 = 3.3\n1.1 - 2.2 = -1.1\n1.1 * 2.2 = 2.42\n1.1 / 2.2 = 0.5\n```\n\n**Note**: The Lua module can only be imported if the Lua version of the interpreter is compatible with the Lua version of the used API libraries.\n\nThis example builds a `lua.exe` and runs the [test.lua][1] script as post build process. The Lua versions are therefore exactly the same.\n\n**Note**: You can create modules like this in C++ too. Just wrap a `extern \"C\"` around your code and especially around the lua includes like I did in the header file.\n\n## External ##\n- [Lua][3]\n\n## Build ##\nThis project uses [CMake][2] to generate platform and compiler-specific build files. \n\nBuild just tested on Windows. Will most likely not work on other platforms. You had to atleast change the `__declspec(dllexport)` when you are using GCC to ```__attribute__((dllexport))``` or ```__attribute__((visibility(\"default\")))``` when GCC version is greater equal than 4. But for simplicity I decided not to do it.\n\n1. Clone the repository with Lua submodule\n    ```\n    git clone --recurse-submodules https://github.com/Seng3694/CLuaModuleExample\n    ```\n2. Generate the build files\n    ```\n    mkdir bin\n    cd bin\n    cmake -G\"Your Generator\" ../CLuaModuleExample\n    ```\n3. Build the files\n    ```\n    cmake --build . --config Release\n    ``` \n\nIf everything went correct you should see this after building:\n```\n1.1 + 2.2 = 3.3\n1.1 - 2.2 = -1.1\n1.1 * 2.2 = 2.42\n1.1 / 2.2 = 0.5\n```\n\nIf there are errors while building, remove the `post_build` custom command in the [CMakeLists.txt][4]. You have to run the `lua` executable on your own and pass the `test.lua` script file as an argument.\n\n[1]:scripts/test.lua\n[2]:https://cmake.org/\n[3]:https://github.com/lua/lua\n[4]:CMakeLists.txt\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseng3694%2Fcluamoduleexample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseng3694%2Fcluamoduleexample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseng3694%2Fcluamoduleexample/lists"}