Skip to content

Commit af02f30

Browse files
committed
improve binding generation
1 parent 5d4fc4f commit af02f30

File tree

2 files changed

+44
-32
lines changed

2 files changed

+44
-32
lines changed

examples/vulkan_bindgen.lua

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ for enum_name, data in pairs(enum_lookups) do
343343
" value: ' .. tostring(s))\n"
344344
)
345345
else
346-
extra_code:put("\tif tonumber(s) then return s end\n")
346+
extra_code:put("\tif type(s) == \"number\" or type(s) == \"cdata\" then return s end\n")
347347
-- Handle table of flags (e.g., {"color", "depth"} -> VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT)
348348
extra_code:put(
349349
"\tif type(s) == 'table' then return combine_flags(lookup, s, '",
@@ -460,8 +460,7 @@ for struct_name in pairs(structs_needing_builders) do
460460
local info = info_structs[struct_name]
461461
local short_name = struct_name:gsub("^Vk", "")
462462
extra_code:put("mod.s.", short_name, " = function(t)\n")
463-
extra_code:put("\tif type(t) ~= 'table' then return t end\n")
464-
extra_code:put("\treturn mod.", struct_name, "({\n")
463+
extra_code:put("\treturn mod.", struct_name, "(t and {\n")
465464
local struct_data = metadata.structs[struct_name]
466465

467466
for _, field in ipairs(struct_data.fields) do
@@ -475,10 +474,7 @@ for struct_name in pairs(structs_needing_builders) do
475474
"\t\t",
476475
key,
477476
" = ",
478-
t_access,
479-
" and mod.e.VkStructureType(",
480-
t_access,
481-
") or mod.VkStructureType('",
477+
" mod.VkStructureType('",
482478
info.stype,
483479
"'),\n"
484480
)
@@ -509,7 +505,7 @@ for struct_name in pairs(structs_needing_builders) do
509505
end
510506
end
511507

512-
extra_code:put("\t})\n")
508+
extra_code:put("\t} or nil)\n")
513509
extra_code:put("end\n")
514510
end
515511

nattlua/definitions/lua/ffi/binding_gen.lua

Lines changed: 40 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,10 @@ local function build_lua(c_header, expanded_defines, extra_lua, options)
144144
-- Emit a type reference, either as-is or as $ with parameterization
145145
-- skip_identifier: if true, don't emit the identifier part (for struct fields)
146146
-- self_struct: name of the struct being defined (for self-referential structs)
147-
local function emit_type_ref(decl, parameterized, skip_name, skip_identifier, self_struct)
147+
-- keep_const: if true, keep const/volatile qualifiers (needed for pointer base types like const char*)
148+
local function emit_type_ref(decl, parameterized, skip_name, skip_identifier, self_struct, keep_const)
148149
if decl.type == "root" then
149-
return emit_type_ref(decl.of, parameterized, skip_name, skip_identifier, self_struct)
150+
return emit_type_ref(decl.of, parameterized, skip_name, skip_identifier, self_struct, keep_const)
150151
end
151152

152153
if decl.type == "type" then
@@ -175,6 +176,9 @@ local function build_lua(c_header, expanded_defines, extra_lua, options)
175176
table.insert(parameterized, mod)
176177
elseif is_custom_type(mod) then
177178
buf:put("$ ")
179+
elseif not keep_const and (mod == "const" or mod == "volatile") then
180+
181+
-- Skip const/volatile for non-pointer struct fields to avoid LuaJIT issues
178182
else
179183
buf:put(mod, " ")
180184
end
@@ -195,7 +199,8 @@ local function build_lua(c_header, expanded_defines, extra_lua, options)
195199
elseif decl.type == "pointer" then
196200
local buf = buffer.new()
197201
-- Pass skip_identifier through for pointer types
198-
local base = emit_type_ref(decl.of, parameterized, skip_name, skip_identifier, self_struct)
202+
-- Pass keep_const=true to preserve const for pointer base types (e.g., const char*)
203+
local base = emit_type_ref(decl.of, parameterized, skip_name, skip_identifier, self_struct, true)
199204
-- Trim trailing whitespace from base
200205
base = base:gsub("%s+$", "")
201206
buf:put(base)
@@ -210,6 +215,9 @@ local function build_lua(c_header, expanded_defines, extra_lua, options)
210215
elseif skip_identifier and not valid_qualifiers[mod] then
211216

212217
-- Skip it (likely an identifier)
218+
elseif not keep_const and (mod == "const" or mod == "volatile") then
219+
220+
-- Skip const/volatile on the pointer itself when not keeping const
213221
else
214222
buf:put(" ", mod)
215223
end
@@ -218,7 +226,7 @@ local function build_lua(c_header, expanded_defines, extra_lua, options)
218226

219227
return tostring(buf)
220228
elseif decl.type == "array" then
221-
local base = emit_type_ref(decl.of, parameterized, skip_name, skip_identifier, self_struct)
229+
local base = emit_type_ref(decl.of, parameterized, skip_name, skip_identifier, self_struct, keep_const)
222230
base = base:gsub("%s+$", "")
223231
local size_str = decl.size or ""
224232
return base .. "[" .. size_str .. "]"
@@ -494,59 +502,67 @@ local function build_lua(c_header, expanded_defines, extra_lua, options)
494502
buf:put(
495503
"ffi.metatype(mod.",
496504
struct_name,
497-
", {__tostring = function(s) return ('struct " .. struct_name .. "[%p]'):format(s) end,__new = function(T, t) if not t then return N(T) end \n"
505+
", {__tostring = function(s) return ('struct " .. struct_name .. "[%p]'):format(s) end,__new = function(T, t) \n"
498506
)
499507

500508
if v.type == "union" then
501509
-- For unions: create object, then assign whichever field is provided
502510
buf:put("local obj = N(T)\n")
511+
buf:put("if not t then return obj end\n")
503512

504513
for i, field in ipairs(v.fields) do
505514
if field.identifier then
506515
if lua_keywords[field.identifier] then
507516
buf:put(
508-
"if t['",
509-
field.identifier,
510-
"'] ~= nil then obj.",
517+
"obj['",
511518
field.identifier,
512-
" = t['",
519+
"'] = t['",
513520
field.identifier,
514-
"'] end\n"
521+
"']"
515522
)
516523
else
517524
buf:put(
518-
"if t.",
519-
field.identifier,
520-
" ~= nil then obj.",
525+
"obj.",
521526
field.identifier,
522527
" = t.",
523-
field.identifier,
524-
" end\n"
528+
field.identifier
525529
)
526530
end
531+
532+
buf:put("\n")
527533
end
528534
end
529535

530536
buf:put("return obj\n")
531537
else
532-
-- For structs: use the original N(T, ...) pattern
533-
buf:put("return N(\n\tT,\n")
538+
-- For structs: use field-by-field assignment to avoid LuaJIT NYI
539+
-- issues with union members (same pattern as unions above)
540+
buf:put("local obj = N(T)\n")
541+
buf:put("if not t then return obj end\n")
534542

535543
for i, field in ipairs(v.fields) do
536544
if field.identifier then
537545
if lua_keywords[field.identifier] then
538-
buf:put("\tt['", field.identifier, "']")
546+
buf:put(
547+
"obj['",
548+
field.identifier,
549+
"'] = t['",
550+
field.identifier,
551+
"']\n"
552+
)
539553
else
540-
buf:put("\tt.", field.identifier)
554+
buf:put(
555+
"obj.",
556+
field.identifier,
557+
" = t.",
558+
field.identifier,
559+
"\n"
560+
)
541561
end
542-
543-
if i ~= #v.fields then buf:put(",") end
544-
545-
buf:put("\n")
546562
end
547563
end
548564

549-
buf:put(")\n")
565+
buf:put("return obj\n")
550566
end
551567

552568
buf:put("end,\n})")

0 commit comments

Comments
 (0)