Hi all,
I ran into a limitation while working on a lua.zig wrapper, and I want to check whether I’m understanding Zig’s design correctly, or whether I’m missing an intended approach.
My practical use case
I have a namespace like this:
const APIs = struct {
pub extern fn lua_createtable(L: *State, narr: c_int, nrec: c_int) callconv(.c) void;
pub extern fn lua_pushinteger(L: *State, n: c_int) callconv(.c) void;
// ...
};
What I want for the public API is:
pub const createtable = APIs.lua_createtable;
pub const pushinteger = APIs.lua_pushinteger;
// ...
So that users (remain parts of my code) can simply write:
const lua = @import("lua.zig");
lua.createtable(...);
lua.pushinteger(...);
(I know there is zlua project in github, but it required to build lua itself into shared library, which is not fill my purpose)
This is currently working fine if I write those aliases manually.
What I hoped to do
Since all the source declarations are already present in APIs, I hoped I could:
- iterate over
@typeInfo(APIs).@"struct".decls - get each declaration name and member
- strip the
lua_prefix (or transformluaL_...as needed) - somehow generate:
pub const {new_name} = {member};
But as far as I can tell, Zig currently allows reflection over decls, and allows type construction for fields via @Struct, but does not allow constructing new declarations or injecting them into a container/module scope.
So the only current options seem to be:
- write aliases manually
- or generate a
.zigfile with codegen modified it (I have other helpers in lua.zig, so I could just replace parts of file, not whole).
My questions
1. Is this limitation intentional because of Zig’s “No hidden control flow” / anti-macro philosophy?
I’m wondering whether declaration generation is intentionally excluded because introducing new declarations from comptime would be considered too close to hidden language-level metaprogramming.
In other words: is the inability to generate decls from reflected decls a deliberate design boundary, rather than just an unimplemented feature?
2. Is there any roadmap or long-term plan for declaration-level metaprogramming?
I’m not necessarily asking for a full macro system, but something like:
- declaration reification
- constructing container decls in
@Struct - or some supported way to generate alias declarations from reflected declarations
Has this been discussed as a possible future direction, or is it considered out of scope?
3. In cases like this, is code generation the recommended Zig-style solution?
For this kind of FFI wrapper ergonomics problem, is the intended answer simply:
“yes, use build-time codegen and generate a
.zigfile”
If so, that’s totally fine — I mainly want to understand whether this is the idiomatic expected approach today. (btw, the usingnamespace is deleted from language, so a separate .zig file can not hide the indirection from user, so the codegen must modify the part of file)
Thanks!