{"id":43796278,"url":"https://github.com/yasuoka/luacstruct","last_synced_at":"2026-02-05T21:07:20.179Z","repository":{"id":41363865,"uuid":"362783846","full_name":"yasuoka/luacstruct","owner":"yasuoka","description":"maps c struct to Lua","archived":false,"fork":false,"pushed_at":"2026-01-31T11:56:02.000Z","size":69,"stargazers_count":17,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-01-31T23:45:08.804Z","etag":null,"topics":["binding","c","lua","mapping","struct","type"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yasuoka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-04-29T10:49:24.000Z","updated_at":"2026-01-31T11:56:06.000Z","dependencies_parsed_at":"2024-05-11T12:40:37.402Z","dependency_job_id":"650e6e9f-e536-4a92-8e32-d3ad2aa8ed2b","html_url":"https://github.com/yasuoka/luacstruct","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yasuoka/luacstruct","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasuoka%2Fluacstruct","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasuoka%2Fluacstruct/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasuoka%2Fluacstruct/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasuoka%2Fluacstruct/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yasuoka","download_url":"https://codeload.github.com/yasuoka/luacstruct/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yasuoka%2Fluacstruct/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29134362,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T20:50:26.975Z","status":"ssl_error","status_checked_at":"2026-02-05T20:49:26.082Z","response_time":65,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["binding","c","lua","mapping","struct","type"],"created_at":"2026-02-05T21:07:19.440Z","updated_at":"2026-02-05T21:07:20.090Z","avatar_url":"https://github.com/yasuoka.png","language":"C","readme":"# LUACSTRUCT - Map C struct to Lua\n\nA simple C source code which provides a lua metatable representing a C\nstruct, can be embedded within your application.  Also it enables\ncontrolling access to the fields of the struct.\n\n  * [How to use](#how-to-use)\n    * [1. Prerequisite](#1-prerequisite)\n    * [2. Prepare](#2-prepare)\n    * [3. Declare a C struct in your application](#3-declare-a-c-struct-in-your-application)\n    * [4. Map an instance of the struct](#4-map-an-instance-of-the-struct)\n    * [5. Declare a enum in your application](#5-declare-a-enum-in-your-application)\n    * [6. Declare a method](#6-declare-a-method)\n\n## How to use\n\n### 1. Prerequisite\n\nThis document assumes that Lua is embed already in your application.\n\n\n### 2. Prepare\n\n```c\n#include \"yourapp_types.h\"          // 3.\n\n#include \u003clua.h\u003e                    // 1.\n#include \"luacstruct.h\"             // 2.\n```\n\n0. copy `luacstruct.h` and `luacstruct.c` to your application, and add\n   `luacstruct.c` in SRCS of Makefile of your application.\n   - luacstruct.c is using `\u003csys/tree.h\u003e` and `\u003csys/queue.h\u003e`.  Copy\n     them if your OS doesn't have any of them.\n1. open a source file which is doing the Lua thing.\n2. include \"luacstruct.h\".\n3. make sure all headers which declare the structs or enums which you\n   want to expose are included.\n\n### 3. Declare a C struct in your application\n\n```c\n// create a new luacstruct for \"struct yourapp_type\"\nluacs_newstruct(L, yourapp_type);\t// don't surround \"...\"\n\n// member fields\nluacs_int_field(L, yourapp_type, field1, 0);  // `field1' field\nluacs_int_field(L, yourapp_type, field2, 0);  // `field2' field\nluacs_strptr_field(L, yourapp_type, name, 0); // `name' field\n\nlua_pop(L, 1);\t\t              // pop the luacstruct\n```\n\nTo expose a C structure, create a new `luacstruct` object for a C struct\nwhich you want to expose, and declare the fields of the struct to the\n`luacstruct` object.\n\n`luacs_newstruct()` is the macro function to create a new `luacstruct`\nobject.  If there is a struct object which has the same name, the\nexisting object is used instead of creating new one.  The function\npushes the object on the stack.  \n\n`luacs_declare_field()` is the function to declare fields.  Usually this\nfunction is not used directly, used through the helper macro functions\nas follows:\n\n```c\n#define luacs_int_field(_L, _type, _field, _flags)            // int\n#define luacs_unsigned_field(_L, _type, _field, _flags)       // unsigned int\n#define luacs_enum_field(_L, _type, _etype, _field, _flags)   // enum\n#define luacs_bool_field(_L, _type, _field, _flags)           // bool\n#define luacs_bytearray_field(_L, _type, _field, _flags)      // byterray\n#define luacs_string_field(_L, _type, _field, _flags)         // char[] represents a string\n#define luacs_wstring_field(_L, _type, _field, _flags)        // wchar_t[] represents\n                                                              // a wide-character string\n#define luacs_strptr_field(_L, _type, _field, _flags)         // pointer to a string\n#define luacs_wstrptr_field(_L, _type, _field, _flags)        // pointer to a wide-character\n                                                              // string\n#define luacs_objref_field(_L, _type, _tname, _field, _flags) // a pointer to an instance of\n                                                              // the _tname struct\n#define luacs_nested_field(_L, _type, _tname, _field, _flags) // nested  _tname struct\n#define luacs_extref_field(_L, _type, _field, _flags)         // can be set an external lua\n                                                              // object manually\n#define luacs_pseudo_field(_L, _type, _field, _flags)         // for a pseudo field.  can be\n                                                              // set any lua object manually\n```\n\nThe meaning of the arguments is as follows:\n\n|Argument |Description|\n|---------|-----------|\n|`_L`     |Specify a lua state by a pointer of `lua_State`|\n|`_type`  |Specify a struct name|\n|`_field` |Specify a field name in the struct|\n|`_flags` |Bit flags.  Specify `LUACS_FREADONLY` if the field must be read only|\n|`_tname` |Specify a type name of the field.  Only for `luacs_objref_field()` or `luacs_objref_field()`|\n|`_etype` |Specify a enum type.  Only for `luacs_enum_field()`|\n\n\n### 4. Map an instance of the struct\n\n```c\nint\nyouapp_do_script(struct youapp_type *self)\n{\n\tlua_getglobal(L, \"yourfunction\");\n\tluacs_newobject(L, \"yourapp_type\", self);\t// here\n\tlua_call(L, 1, 0);\n}\n```\n\nTo map an instance of the sctruct, the struct must be declared already\nwith a name.  Then call `luacs_newobject()` with the name to create a\nmapped Lua object.\n\nOn Lua, you can use it naturally.\n\n```lua\nyourfunction = function(self)\n\tprint(self.name, self.field1, self.field2)\n\tself.field1 = 5\n\tfor k, v in pairs(self) do\n\t\tprint(k, v)\n\tend\nend\n```\n\nIn above case, lifetime of the instance in Lua and C will be managed\nseparately.  You can also create an object which will be freed in the\nLua's garbage collection by passing NULL to the ptr argment for\n`luacs_newobject()`.\n\n```c\n\tstruct youapp_type *self;\n\tluacs_newobject(L, \"youapp_type\", NULL);\n\tself = luacs_object_pointer(L, -1);\n\treturn (1);\n\t/* \"self\" will be released along with the lua object */\n```\n\nAs for `pairs()`, `pairs()` will work as it is on Lua 5.2 and later\nsince `__pairs()` meta method is provided for objects created by\n`luacs_newobject()`.  For Lua 5.1, you need to override the global\n`pairs()` function like follows:\n\n```lua\nif _VERSION == \"Lua 5.1\" then\n\t_pairs = pairs\n\tpairs = function(t)\n\t    local mt = getmetatable(t)\n\t    if mt and mt.__pairs then\n\t\treturn mt.__pairs(t)\n\t    end\n\t    return _pairs(t)\n\tend\nend\n```\n\n### 5. Declare a enum in your application\n\n```c\n/*\n * Declare the following enum\n * enum yourapp_color {\n *     YOURAPP_RED,\n *     YOURAPP_GREEN,\n *     YOURAPP_BLUE\n * }\n */\n\n// create a new luacenum for \"enum yourapp_color\"\nluacs_newenum(L, yourapp_color);\t      // don't surround \"..\"\n\nluacs_enum_declare_value(L, \"RED\",   YOURAPP_RED);\nluacs_enum_declare_value(L, \"GREEN\", YOURAPP_GREEN);\nluacs_enum_declare_value(L, \"BLUE\",  YOURAPP_BLUE);\n\nlua_pop(L, 1);\t\t              // pop the enum\n```\n\nTo expose an enum, create a new `luacenum` object for an enum which you\nwant to expose, and declare the values of the enum for the `luacenum`\nobject.\n\n`luacs_newenum()` is the function to create a new `luacenum` object.  If\nthere is an enum object which has the same name, the existing object is\nused instead of creating new one.  The function pushes the object on the\nstack.  \n\n`luacs_enum_declare_value()` macro function is used to declare the enum\nvalues.\n\nAfter the enum is declared, it can be used when declaring a enum field\nfor a ``luacstruct`:\n\n```c\n/*\n * Use it in the following struct\n *\n * struct yourapp_type2 {\n *     enum yourapp_color color\n *     :\n * }\n */\nluacs_newstruct(L, yourapp_type2);\n\nluacs_enum_field(L, yourapp_type2, yourapp_color, color, 0);\t\n    :\nlua_pop(L, 1);\t\t              // pop the struct\n```\n\nAlso the `luacenum` object can be expose as a set of constants:\n```c\nluacs_newenum(L, yourapp_color);\nlua_setglobal(L, \"COLOR\");\n```\nYou can use it in Lua:\n```lua\nlocal color = COLOR.RED\t\t-- or COLOR.BLUE, COLOR.GREEN\n```\n\nAlso it has some useful methods:\n```lua\ncolor = COLOR.get(1)\t\t-- get COLOR object by an integer\nCOLOR.memberof(obj)\t\t-- check whether an object is COLOR\nlocal ival = color:tointeger()\t-- get an integer value\nprint(color)\t\t\t-- pretty output like \"GREEN(1)\"\n```\n\n### 6. Declare a method\n\n```c\nstruct person {\n\tconst char\t*name;\n\tint\t\t height;\t/* in cm */\n\tint\t\t weight;\t/* in kg */\n};\n\n// declare struct person\nluacs_newstruct(L, person);\nluacs_strptr_field(L, person, name, 0);\nluacs_int_field(L, person, height, 0);\nluacs_int_field(L, person, weight, 0);\n```\n\nTo add bmi() method which calculates BMI(body math index) to this object,\ncreate a C function which returns BMI and call `luacs_declare_method`\nfor it.\n\n```c\nstatic int\nperson_bmi(lua_State *L)\n{\n\tstruct person *self;\n\n\t/* the pointer is passed through 1st upvalue */\n\tself = lua_touserdata(L, lua_upvalueindex(1));\n\tlua_pushnumber(L, ((double)self-\u003eweight / (self-\u003eheight *\n\t    self-\u003eheight)) * 10000.0);\n\n\treturn (1);\n}\n\nluacs_declare_method(L, \"bmi\", person_bmi);\n```\n\nYou can also override __tostring() in the same way.\n\n```c\nstatic int\nperson_tostring(lua_State *L)\n{\n\tstruct person *self;\n\n\tself = luacs_object_pointer(L, 1);\n\tlua_pushfstring(L, \"%s(%d,%d)\", self-\u003ename, self-\u003eheight, self-\u003eweight);\n\tfree(buf);\n\n\treturn (1);\n}\n\nluacs_declare_method(L, \"__tostring\", person_tostring);\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyasuoka%2Fluacstruct","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyasuoka%2Fluacstruct","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyasuoka%2Fluacstruct/lists"}