cpp2ffi: split with cpp2ffi_extra.lua

This commit is contained in:
sonoro1234
2026-08-13 11:23:16 +02:00
parent a5ae0de007
commit ba1e982860
2 changed files with 645 additions and 689 deletions

View File

@@ -1,100 +1,22 @@
local M = {}
local insert = table.insert
local function ToStr(t,dometatables)
local function basicToStr (o)
if type(o) == "number" or type(o)=="boolean" then
return tostring(o)
elseif type(o) == "string" then
return string.format("%q", o)
else
return tostring(o) --"nil"
end
end
local strTG = {}
--local basicToStr= basicSerialize --tostring
if type(t) ~="table" then return basicToStr(t) end
local recG = 0
local nameG="SELF"..recG
local ancest ={}
local function _ToStr(t,strT,rec,name)
if ancest[t] then
strT[#strT + 1]=ancest[t]
return
end
rec = rec + 1
ancest[t]=name
strT[#strT + 1]='{'
local count=0
-------------
--if t.name then strT[#strT + 1]=string.rep("\t",rec).."name:"..tostring(t.name) end
----------------
for k,v in pairs(t) do
count=count+1
strT[#strT + 1]="\n"
local kstr
if type(k) == "table" then
local name2=string.format("%s.KEY%d",name,count)
strT[#strT + 1]=string.rep("\t",rec).."["
local strTK = {}
_ToStr(k,strTK,rec,name2)
kstr=table.concat(strTK)
strT[#strT + 1]=kstr.."]="
else
kstr = basicToStr(k)
strT[#strT + 1]=string.rep("\t",rec).."["..kstr.."]="
end
if type(v) == "table" then
local name2=string.format("%s[%s]",name,kstr)
_ToStr(v,strT,rec,name2)
else
strT[#strT + 1]=basicToStr(v)
end
end
if dometatables then
local mt = getmetatable(t)
if mt then
local namemt = string.format("%s.METATABLE",name)
local strMT = {}
_ToStr(mt,strMT,rec,namemt)
local metastr=table.concat(strMT)
strT[#strT + 1] = "\n"..string.rep("\t",rec).."[METATABLE]="..metastr
end
end
strT[#strT + 1]='}'
rec = rec - 1
return
end
_ToStr(t,strTG,recG,nameG)
return table.concat(strTG)
end
M.ToStr = ToStr
function M.prtable(...)
for i=1, select('#', ...) do
local t = select(i, ...)
print(ToStr(t))
print("\n")
end
end
local function deepcopy(object)
local lookup_table = {}
local function _copy(object)
--assert(object~=REST)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
M.deepcopy = deepcopy
local extra = require"cpp2ffi_extra"
M.prtable = extra.prtable
M.table_do_sorted = extra.table_do_sorted
M.deepcopy = extra.deepcopy
M.copyfile = extra.copyfile
local save_data = extra.save_data
M.save_data = save_data
local read_data = extra.read_data
M.read_data = read_data
M.func_implementation = extra.func_implementation
M.func_header_generate_structs = extra.func_header_generate_structs
M.func_header_generate_funcs = extra.func_header_generate_funcs
M.func_header_generate = extra.func_header_generate
M.serializeTableF = extra.serializeTableF
------------------------------------------------------------
local function str_split(str, pat)
local t = {}
local fpat = "(.-)" .. pat
@@ -332,42 +254,6 @@ local function parse_enum_value(value, allenums,dontpost)
end
M.parse_enum_value = parse_enum_value
--------------------------------------------------------------------------
local function save_data(filename,...)
local file,err = io.open(filename,"w")
if not file then error(err) end
for i=1, select('#', ...) do
local data = select(i, ...)
file:write(data)
end
file:close()
end
M.save_data = save_data
----------------------------------------
local function read_data(filename)
local hfile,err = io.open(filename,"r")
if not hfile then error(err) end
local hstrfile = hfile:read"*a"
hfile:close()
return hstrfile
end
M.read_data = read_data
------------------------------------------------------------
local function copyfile(src,dst,blocksize)
blocksize = blocksize or 1024*4
print( "copyfile", src, dst)
local srcf, err = io.open(src,"rb")
if not srcf then error(err) end
local dstf, err = io.open(dst,"wb")
if not dstf then error(err) end
while true do
local data = srcf:read(blocksize)
if not data then break end
dstf:write(data)
end
srcf:close()
dstf:close()
end
M.copyfile = copyfile
--gives the re table
local function getRE()
@@ -1560,7 +1446,7 @@ local function ADDnonUDT(FP)
asp = "("
for i,v in ipairs(def.argsT) do
local name = v.name
argsTN[i] = deepcopy(v)
argsTN[i] = M.deepcopy(v)
if v.ret then --function pointer
local f_ = v.has_cdecl and "(__cdecl*" or "(*"
asp = asp .. v.ret .. f_ .. v.name .. ")" .. v.signature .. ","
@@ -1820,91 +1706,8 @@ local function printItems(items)
end
end
-------------------------------json saving
--avoid mixed tables (with string and integer keys)
local function json_prepare(defs)
--delete signatures in function
for k,def in pairs(defs) do
for k2,v in pairs(def) do
if type(k2)=="string" then
def[k2] = nil
end
end
end
return defs
end
local function paramListWithoutDots(params)
local i, j = string.find(params, "%.%.%.")
while i > 1 do
i = i - 1
local c = string.sub(params,i,i)
if c == "," then
return string.sub(params, 1, i-1) .. params:sub(j+1)
elseif c == "(" then
return string.sub(params, 1, i) .. params:sub(j+1)
end
end
error("paramListWithoutDots failed")
return "()"
end
local function save_output(self)
--add VARGS0
local defsVARG = {}
for k,defs in pairs(self.defsT) do
for i, def in ipairs(defs) do
if def.isvararg then
--print("vararg",k,#def)
local def1 = deepcopy(def)
def1.isvararg = nil
def1.isVARG0 = true
def1.argsT[#def1.argsT] = nil
def1.args = paramListWithoutDots(def1.args)
def1.call_args_old = paramListWithoutDots(def1.call_args_old)
def1.call_args = paramListWithoutDots(def1.call_args)
def1.signature = paramListWithoutDots(def1.signature)
def1.cimguiname = def1.cimguiname.."0"
def1.ov_cimguiname = def1.ov_cimguiname.."0"
defsVARG[k.."0"] = defsVARG[k.."0"] or {}
table.insert(defsVARG[k.."0"], def1)
end
end
end
for k,def in pairs(defsVARG) do
self.defsT[k] = def
end
--add manual not present in module
for k,v in pairs(self.manuals) do
if not self.defsT[k] then
--print("add manual",k)
self.defsT[k] = {v}
else
--print("skipped manual",k)
end
end
----------------------
save_data("./output/overloads.txt",self.overloadstxt)
save_data("./output/definitions.lua",M.serializeTableF(self.defsT))
save_data("./output/structs_and_enums.lua",M.serializeTableF(self.structs_and_enums_table))
save_data("./output/typedefs_dict.lua",M.serializeTableF(self.typedefs_dict))
save_data("./output/constants.lua",M.serializeTableF(self.constants))
local json = require"json"
local json_opts = {dict_on_empty={defaults=true}}
save_data("./output/definitions.json",json.encode(json_prepare(self.defsT),json_opts))
save_data("./output/structs_and_enums.json",json.encode(self.structs_and_enums_table))
save_data("./output/typedefs_dict.json",json.encode(self.typedefs_dict))
save_data("./output/constants.json",json.encode(self.constants))
local modulename = self.modulename
copyfile("./output/"..modulename..".h", "../"..modulename..".h")
copyfile("./output/"..modulename..".cpp", "../"..modulename..".cpp")
os.remove("./output/"..modulename..".h")
os.remove("./output/"..modulename..".cpp")
end
-------------
local numerr = 0 --for popen error file
function M.Parser()
@@ -1930,7 +1733,7 @@ function M.Parser()
par.skip_template = {}
par.skip_convert_gen = {}
par.save_output = save_output
par.save_output = extra.save_output
par.genConversors = genConversions
par.gen_structs_c = gen_structs_c
function par:insert(line,loca)
@@ -3677,177 +3480,7 @@ function M.Parser()
end
return par
end
-- more compact serialization
local function basicSerialize (o)
if type(o) == "number" then
return string.format("%.17g", o)
elseif type(o)=="boolean" then
return tostring(o)
elseif type(o) == "string" then
return string.format("%q", o)
elseif pcall(function() return o.__serialize end) then
return o.__serialize(o)
elseif type(o)=="cdata" then
return cdataSerialize(o)
else
return tostring(o) --"nil"
end
end
-- very readable and now suited for cyclic tables
local kw = {['and'] = true, ['break'] = true, ['do'] = true, ['else'] = true,
['elseif'] = true, ['end'] = true, ['false'] = true, ['for'] = true,
['function'] = true, ['goto'] = true, ['if'] = true, ['in'] = true,
['local'] = true, ['nil'] = true, ['not'] = true, ['or'] = true,
['repeat'] = true, ['return'] = true, ['then'] = true, ['true'] = true,
['until'] = true, ['while'] = true}
function tb2st_serialize(t,options)
options = options or {}
local function sorter(a,b)
if type(a)==type(b) then
return a<b
elseif type(a)=="number" then
return true
else
assert(type(b)=="number")
return false
end
end
local function serialize_key(val, dodot, pretty)
local dot = dodot and "." or ""
if type(val)=="string" then
if val:match '^[_%a][_%w]*$' and not kw[val] then
return dot..tostring(val)
else
return "[\""..tostring(val).."\"]"
end
elseif (not pretty) and (not dodot) and (type(val) == "number") and (math.floor(val)==val) then
return --array index
else
return "["..tostring(val).."]"
end
end
local function serialize_key_name(val)
return serialize_key(val, true)
end
local insert = table.insert
local function _tb2st(t,saved,sref,level,name)
saved = saved or {} -- initial value
level = level or 0
sref = sref or {}
name = name or "t"
if type(t)=="table" then
if saved[t] then
sref[#sref+1] = {saved[t],name}
return"nil"
else
saved[t] = name
local ordered_keys = {}
for k,v in pairs(t) do
insert(ordered_keys,k)
end
table.sort(ordered_keys,sorter)
local str2 = {}
insert(str2,"{")
if options.pretty then insert(str2,"\n") end
for _,k in ipairs(ordered_keys) do
if options.pretty then insert(str2,(" "):rep(level+1)) end
local v = t[k]
local kser = serialize_key(k, nil, options.pretty)
insert(str2, (kser and (kser .."=") or ""))
if type(v)~="table" then
insert(str2, basicSerialize(v))
else
local name2 = name .. serialize_key_name(k)
insert(str2,_tb2st(v,saved,sref,level+1,name2))
end
if options.pretty then insert(str2,",\n") else insert(str2, ",") end
end
str2[#str2] = "}"
if level == 0 then
--insert(str2, 1,"local ffi = require'ffi'\nlocal t=")
insert(str2, 1,"local t=")
for i,v in ipairs(sref) do
insert(str2, "\n"..v[2].."="..v[1])
end
insert(str2,"\n return t")
end
return table.concat(str2)
end
else
return basicSerialize(t)
end
end
return(_tb2st(t))
end
M.tb2st_serialize = tb2st_serialize
------serializeTable("anyname",table) gives a string that recreates the table with dofile(generated_string)
local function serializeTable(name, value, saved)
local function basicSerialize (o)
if type(o) == "number" or type(o)=="boolean" then
return tostring(o)
elseif type(o) == "string" then
return string.format("%q", o)
else
return "nil"
end
end
local string_table = {}
if not saved then
table.insert(string_table, "local "..name.." = ")
else
table.insert(string_table, name.." = ")
end
saved = saved or {} -- initial value
if type(value) == "number" or type(value) == "string" or type(value)=="boolean" then
table.insert(string_table,basicSerialize(value).."\n")
elseif type(value) == "table" then
if saved[value] then -- value already saved?
table.insert(string_table,saved[value].."\n")
else
saved[value] = name -- save name for next time
table.insert(string_table, "{}\n")
---[[
local ordered_keys = {}
for k,v in pairs(value) do
table.insert(ordered_keys,k)
end
local function sorter(a,b)
if type(a)==type(b) then
return a<b
elseif type(a)=="number" then
return true
else
assert(type(b)=="number")
return false
end
end
table.sort(ordered_keys,sorter)
for _,k in ipairs(ordered_keys) do
local v = value[k]
--]]
-- for k,v in pairs(value) do -- save its fields
local fieldname = string.format("%s[%s]", name,basicSerialize(k))
table.insert(string_table, serializeTable(fieldname, v, saved))
end
end
--else
--error("cannot save a " .. type(value))
end
return table.concat(string_table)
end
-- M.serializeTable = serializeTable
-- M.serializeTableF = function(t)
-- return M.serializeTable("defs",t).."\nreturn defs"
-- end
M.serializeTableF = function(t) return tb2st_serialize(t,{pretty=true}) end --new serialization more compact
--iterates lines from a gcc/clang -E in a specific location
local function location(file,locpathT,defines,COMPILER,keepemptylines)
local define_re = "^#define%s+([^%s]+)%s+(.+)$"
@@ -3936,300 +3569,8 @@ local function location(file,locpathT,defines,COMPILER,keepemptylines)
return location_it
end
M.location = location
---------------------- C writing functions
local function ImGui_f_implementation(def)
local outtab = {}
local ptret = def.retref and "&" or ""
table.insert(outtab,"CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname..def.args.."\n")
table.insert(outtab,"{\n")
local namespace = def.namespace and def.namespace.."::" or ""
--namespace = def.is_static_function and namespace..def.stname.."::" or namespace
if def.isvararg then
local call_args = def.call_args:gsub("%.%.%.","args")
table.insert(outtab," va_list args;\n")
table.insert(outtab," va_start(args, fmt);\n")
if def.ret~="void" then
table.insert(outtab," "..def.ret.." ret = "..namespace..def.funcname.."V"..call_args..";\n")
else
table.insert(outtab," "..namespace..def.funcname.."V"..call_args..";\n")
end
table.insert(outtab," va_end(args);\n")
if def.ret~="void" then
table.insert(outtab," return ret;\n")
end
table.insert(outtab,"}\n")
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args).."\n")
table.insert(outtab, "{\n")
local returnword = "return "
if def.ret=="void" then returnword = "" end
table.insert(outtab, " "..returnword..def.ov_cimguiname..paramListWithoutDots(def.call_args_old)..";\n")
table.insert(outtab, "}\n")
table.insert(outtab, "#endif\n")
elseif def.nonUDT then
if def.nonUDT == 1 then
--table.insert(outtab," *pOut = "..namespace..def.funcname..def.call_args..";\n")
insert(outtab," return ConvertFromCPP_"..def.conv.."("..namespace..def.funcname..def.call_args..");\n")
elseif def.nonUDT == 2 then
insert(outtab," return reinterpret_cast<"..def.ret..">("..ptret..namespace..def.funcname..def.call_args..");\n")
elseif def.nonUDT == "string" then
insert(outtab," static std::string str;\n")
insert(outtab," str.assign("..ptret.."self->"..def.funcname..def.call_args..");\n")
insert(outtab," return str.c_str();\n")
elseif def.nonUDT == "opaque" then
insert(outtab," static auto opq = "..ptret..namespace..def.funcname..def.call_args..";\n")
insert(outtab," opq = "..ptret..namespace..def.funcname..def.call_args..";\n")
insert(outtab," return &opq;\n")
end
table.insert(outtab,"}\n")
else --standard ImGui
table.insert(outtab," return "..ptret..namespace..def.funcname..def.call_args..";\n")
table.insert(outtab,"}\n")
end
--table.insert(outtab,"}\n")
return table.concat(outtab, "")
end
local function struct_f_implementation(def)
local outtab = {}
local empty = def.args:match("^%(%)") --no args
local ptret = def.retref and "&" or ""
local imgui_stname = def.stname
table.insert(outtab,"CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname..def.args.."\n")
table.insert(outtab,"{\n")
if def.isvararg then
local call_args = def.call_args:gsub("%.%.%.","args")
table.insert(outtab," va_list args;\n")
table.insert(outtab," va_start(args, fmt);\n")
if def.ret~="void" then
table.insert(outtab," "..def.ret.." ret = self->"..def.funcname.."V"..call_args..";\n")
else
table.insert(outtab," self->"..def.funcname.."V"..call_args..";\n")
end
table.insert(outtab," va_end(args);\n")
if def.ret~="void" then
table.insert(outtab," return ret;\n")
end
table.insert(outtab,"}\n")
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args).."\n")
table.insert(outtab, "{\n")
local returnword = "return "
if def.ret=="void" then returnword = "" end
table.insert(outtab, " "..returnword..def.ov_cimguiname.."(self,"..paramListWithoutDots(def.call_args_old):sub(2,-1)..";\n")
table.insert(outtab, "}\n")
table.insert(outtab, "#endif\n")
elseif def.nonUDT then
if def.nonUDT == 1 then
--table.insert(outtab," *pOut = self->"..def.funcname..def.call_args..";\n")
--local typret = (def.ret):gsub("const ","")
insert(outtab," return ConvertFromCPP_"..def.conv.."(self->"..def.funcname..def.call_args..");\n")
elseif def.nonUDT == 2 then
insert(outtab," return reinterpret_cast<"..def.ret..">("..ptret.."self->"..def.funcname..def.call_args..");\n")
elseif def.nonUDT == "string" then
insert(outtab," static std::string str;\n")
insert(outtab," str.assign("..ptret.."self->"..def.funcname..def.call_args..");\n")
insert(outtab," return str.c_str();\n")
elseif def.nonUDT == "opaque" then
insert(outtab," static auto opq = "..ptret.."self->"..def.funcname..def.call_args..";\n")
insert(outtab," opq = "..ptret.."self->"..def.funcname..def.call_args..";\n")
insert(outtab," return &opq;\n")
end
table.insert(outtab,"}\n")
else --standard struct
table.insert(outtab," return "..ptret.."self->"..def.funcname..def.call_args..";\n")
table.insert(outtab,"}\n")
end
return table.concat(outtab, "")
end
local function func_implementation(FP)
local outtab = {}
for _,t in ipairs(FP.funcdefs) do
repeat -- continue simulation
if not t.cimguiname then break end
local cimf = FP.defsT[t.cimguiname]
local def = cimf[t.signature]
assert(def)
local custom
if FP.custom_implementation then
custom = FP.custom_implementation(outtab, def, FP)
end
local manual = FP.get_manuals(def)
if not custom and not manual and not def.templated and not FP.get_skipped(def) --and not (FP.opaque_structs[def.stname] and not def.is_static_function)
then
if def.constructor then
local tab = {}
assert(def.stname ~= "","constructor without struct")
local empty = def.args:match("^%(%)") --no args
table.insert(tab,"CIMGUI_API "..def.stname.."* "..def.ov_cimguiname..(empty and "(void)" or def.args).."\n")
table.insert(tab,"{\n")
table.insert(tab," return IM_NEW("..def.stname..")"..def.call_args..";\n")
table.insert(tab,"}\n")
if FP.CONSTRUCTORS_GENERATION then
table.insert(tab,"CIMGUI_API void "..def.ov_cimguiname.."_Construct("..def.stname.."* self"..(empty and "" or ","..def.args:sub(2,-2))..")\n")
table.insert(tab,"{\n")
table.insert(tab," IM_PLACEMENT_NEW(self)"..def.stname..def.call_args..";\n")
table.insert(tab,"}\n")
end
table.insert(outtab, table.concat(tab, ""))
elseif def.destructor then
local tab = {}
local args = "("..def.stname.."* self)"
local fname = def.stname.."_destroy"
table.insert(tab,"CIMGUI_API void "..fname..args.."\n")
table.insert(tab,"{\n")
table.insert(tab," IM_DELETE(self);\n")
table.insert(tab,"}\n")
table.insert(outtab, table.concat(tab, ""))
elseif def.stname == "" or def.is_static_function then
table.insert(outtab, ImGui_f_implementation(def))
else -- stname
table.insert(outtab, struct_f_implementation(def))
end
end
if FP.custom_function_post then
FP:custom_function_post(outtab, def)
end
until true
end
local conversors = FP:genConversors()
local cimplem = conversors .. table.concat(outtab)
return cimplem
end
M.func_implementation = func_implementation
local function table_do_sorted(t,f)
local sorted = {}
for k,v in pairs(t) do
table.insert(sorted,k)
end
table.sort(sorted)
for ii,k in ipairs(sorted) do
f(k,t[k])
end
end
M.table_do_sorted = table_do_sorted
local function func_header_generate_structs(FP)
local outtab = {}--"\n/////func_header_generate_structs\n"}
M.prtable("embeded_structs",FP.embeded_structs)
table_do_sorted(FP.embeded_structs,function(k,v)
if not FP.typenames[k] then
print("embeded",k,v)
table.insert(outtab,"typedef "..v.." "..k..";\n")
end
end)
table_do_sorted(FP.embeded_enums,function(k,v) table.insert(outtab,"typedef "..v.." "..k..";\n") end)
--table.insert(outtab, "\n//////////templates\n")
table_do_sorted(FP.templates,function(ttype,v)
--print("func_header_generate_structs",ttype)
if not (ttype == "std::function") then
table_do_sorted(v,function(ttypein,te)
local ttype2 = ttype:gsub("::","_") --std::string
table.insert(outtab,"typedef "..ttype.."<"..ttypein.."> "..ttype2.."_"..te..";\n")
end)
end
end)
--M.prtable("typenames",FP.typenames)
table_do_sorted(FP.opaque_structs,function(k,v)
if not FP.typenames[k] then
table.insert(outtab,"typedef "..v.." "..k..";\n")
--table.insert(outtab,"typedef const "..v.."* "..k.."_opq;\n")
--table.insert(outtab,"typedef "..v.."* "..k.."_opq;\n")
end
end)
--table.insert(outtab, "\n//////////end func header\n")
return outtab
end
M.func_header_generate_structs = func_header_generate_structs
local function func_header_generate_funcs(FP)
local outtab = {}
for _,t in ipairs(FP.funcdefs) do
if t.cimguiname then
local cimf = FP.defsT[t.cimguiname]
local def = cimf[t.signature]
assert(def,t.signature..t.cimguiname)
local custom
if FP.custom_header then
custom = FP.custom_header(outtab, def)
end
local manual = FP.get_manuals(def)
if not custom and not manual and not def.templated and not FP.get_skipped(def) --and not (FP.opaque_structs[def.stname] and not def.is_static_function)
then
local addcoment = "" --def.comment or ""
local empty = def.args:match("^%(%)") --no args
if def.constructor then
assert(def.stname ~= "","constructor without struct")
table.insert(outtab,"CIMGUI_API "..def.stname.."* "..def.ov_cimguiname ..(empty and "(void)" or def.args)..";"..addcoment.."\n")
if FP.CONSTRUCTORS_GENERATION then
outtab[#outtab] = outtab[#outtab].."\nCIMGUI_API void "..def.ov_cimguiname.."_Construct("..def.stname.."* self"..(empty and "" or ","..def.args:sub(2,-2))..");\n"
end
elseif def.destructor then
table.insert(outtab,"CIMGUI_API void "..def.ov_cimguiname..def.args..";"..addcoment.."\n")
else --not constructor
--local ret = FP.nP_ret[def.ret] or def.ret
local ret = def.ret
if def.stname == "" or def.is_static_function then --ImGui namespace or top level
table.insert(outtab,"CIMGUI_API "..ret.." ".. def.ov_cimguiname ..(empty and "(void)" or def.args)..";"..addcoment.."\n")
if def.isvararg then
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args)..";\n")
table.insert(outtab, "#endif\n")
end
else
table.insert(outtab,"CIMGUI_API "..ret.." "..def.ov_cimguiname..def.args..";"..addcoment.."\n")
if def.isvararg then
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args)..";\n")
table.insert(outtab, "#endif\n")
end
end
end
end
if FP.custom_function_post then
FP:custom_function_post(outtab, def)
end
else --not cimguiname
table.insert(outtab,t.comment:gsub("%%","%%%%").."\n")-- %% substitution for gsub
end
end
return outtab
end
M.func_header_generate_funcs = func_header_generate_funcs
local function func_header_generate(FP)
local outtab = func_header_generate_structs(FP)
table.insert(outtab, 1, "\n#ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n")
table.insert(outtab,"#endif //CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n")
local outtabf = func_header_generate_funcs(FP)
outtabf = table.concat(outtabf)
assert(type(outtabf)=="string")
--outtabf = M.header_subs_nonPOD(FP,outtabf)
local cfuncsstr = table.concat(outtab)..outtabf
cfuncsstr = cfuncsstr:gsub("\n+","\n") --several empty lines to one empty line
return cfuncsstr
end
M.func_header_generate = func_header_generate
function M.GetScriptArgs(defines,...)
assert(_VERSION=='Lua 5.1',"Must use LuaJIT")
assert(bit,"Must use LuaJIT")
@@ -4279,9 +3620,9 @@ function M.GetScriptArgs(defines,...)
return COMPILER, CPRE, INTERNAL_GENERATION,COMMENTS_GENERATION
end
--[=[
-- tests
---------------------- tests
--[=[
local code = [[
int pedro;
@@ -4296,7 +3637,7 @@ uno,
dos
};
]]
]]
local parser = M.Parser()
--for line in code:gmatch("[^\n]+") do
for line in code:gmatch'(.-)\r?\n' do
@@ -4304,22 +3645,24 @@ for line in code:gmatch'(.-)\r?\n' do
parser:insert(line,"11")
end
parser:do_parse()
M.prtable(parser)
--M.prtable(parser)
M.prtable(parser:gen_structs_and_enums_table())
--]=]
--print(clean_spaces[[ImVec2 ArcFastVtx[12 * 1];]])
--[=[
local code = [[ImU32 Storage[(BITCOUNT + 31) >> 5];]]
--local code = [[ImU32 Storage[37 + 2];]]
local parser = M.Parser()
parser:insert(code,"11")
--parser:do_parse()
--M.prtable(parser)
local tab={}
print(type(code),code)
print(clean_spaces(code))
parser:parse_struct_line(code,tab)
M.prtable(tab)
parser:do_parse()
M.prtable(parser)
-- local tab={}
-- print(type(code),code)
-- print(clean_spaces(code))
-- parser:parse_struct_line(code,tab,"")
-- M.prtable(tab)
--]=]

613
generator/cpp2ffi_extra.lua Normal file
View File

@@ -0,0 +1,613 @@
local insert = table.insert
local function ToStr(t,dometatables)
local function basicToStr (o)
if type(o) == "number" or type(o)=="boolean" then
return tostring(o)
elseif type(o) == "string" then
return string.format("%q", o)
else
return tostring(o) --"nil"
end
end
local strTG = {}
--local basicToStr= basicSerialize --tostring
if type(t) ~="table" then return basicToStr(t) end
local recG = 0
local nameG="SELF"..recG
local ancest ={}
local function _ToStr(t,strT,rec,name)
if ancest[t] then
strT[#strT + 1]=ancest[t]
return
end
rec = rec + 1
ancest[t]=name
strT[#strT + 1]='{'
local count=0
-------------
--if t.name then strT[#strT + 1]=string.rep("\t",rec).."name:"..tostring(t.name) end
----------------
for k,v in pairs(t) do
count=count+1
strT[#strT + 1]="\n"
local kstr
if type(k) == "table" then
local name2=string.format("%s.KEY%d",name,count)
strT[#strT + 1]=string.rep("\t",rec).."["
local strTK = {}
_ToStr(k,strTK,rec,name2)
kstr=table.concat(strTK)
strT[#strT + 1]=kstr.."]="
else
kstr = basicToStr(k)
strT[#strT + 1]=string.rep("\t",rec).."["..kstr.."]="
end
if type(v) == "table" then
local name2=string.format("%s[%s]",name,kstr)
_ToStr(v,strT,rec,name2)
else
strT[#strT + 1]=basicToStr(v)
end
end
if dometatables then
local mt = getmetatable(t)
if mt then
local namemt = string.format("%s.METATABLE",name)
local strMT = {}
_ToStr(mt,strMT,rec,namemt)
local metastr=table.concat(strMT)
strT[#strT + 1] = "\n"..string.rep("\t",rec).."[METATABLE]="..metastr
end
end
strT[#strT + 1]='}'
rec = rec - 1
return
end
_ToStr(t,strTG,recG,nameG)
return table.concat(strTG)
end
local function prtable(...)
for i=1, select('#', ...) do
local t = select(i, ...)
print(ToStr(t))
print("\n")
end
end
-- more compact serialization
local function basicSerialize (o)
if type(o) == "number" then
return string.format("%.17g", o)
elseif type(o)=="boolean" then
return tostring(o)
elseif type(o) == "string" then
return string.format("%q", o)
elseif pcall(function() return o.__serialize end) then
return o.__serialize(o)
elseif type(o)=="cdata" then
return cdataSerialize(o)
else
return tostring(o) --"nil"
end
end
-- very readable and now suited for cyclic tables
local kw = {['and'] = true, ['break'] = true, ['do'] = true, ['else'] = true,
['elseif'] = true, ['end'] = true, ['false'] = true, ['for'] = true,
['function'] = true, ['goto'] = true, ['if'] = true, ['in'] = true,
['local'] = true, ['nil'] = true, ['not'] = true, ['or'] = true,
['repeat'] = true, ['return'] = true, ['then'] = true, ['true'] = true,
['until'] = true, ['while'] = true}
function tb2st_serialize(t,options)
options = options or {}
local function sorter(a,b)
if type(a)==type(b) then
return a<b
elseif type(a)=="number" then
return true
else
assert(type(b)=="number")
return false
end
end
local function serialize_key(val, dodot, pretty)
local dot = dodot and "." or ""
if type(val)=="string" then
if val:match '^[_%a][_%w]*$' and not kw[val] then
return dot..tostring(val)
else
return "[\""..tostring(val).."\"]"
end
elseif (not pretty) and (not dodot) and (type(val) == "number") and (math.floor(val)==val) then
return --array index
else
return "["..tostring(val).."]"
end
end
local function serialize_key_name(val)
return serialize_key(val, true)
end
local insert = table.insert
local function _tb2st(t,saved,sref,level,name)
saved = saved or {} -- initial value
level = level or 0
sref = sref or {}
name = name or "t"
if type(t)=="table" then
if saved[t] then
sref[#sref+1] = {saved[t],name}
return"nil"
else
saved[t] = name
local ordered_keys = {}
for k,v in pairs(t) do
insert(ordered_keys,k)
end
table.sort(ordered_keys,sorter)
local str2 = {}
insert(str2,"{")
if options.pretty then insert(str2,"\n") end
for _,k in ipairs(ordered_keys) do
if options.pretty then insert(str2,(" "):rep(level+1)) end
local v = t[k]
local kser = serialize_key(k, nil, options.pretty)
insert(str2, (kser and (kser .."=") or ""))
if type(v)~="table" then
insert(str2, basicSerialize(v))
else
local name2 = name .. serialize_key_name(k)
insert(str2,_tb2st(v,saved,sref,level+1,name2))
end
if options.pretty then insert(str2,",\n") else insert(str2, ",") end
end
str2[#str2] = "}"
if level == 0 then
--insert(str2, 1,"local ffi = require'ffi'\nlocal t=")
insert(str2, 1,"local t=")
for i,v in ipairs(sref) do
insert(str2, "\n"..v[2].."="..v[1])
end
insert(str2,"\n return t")
end
return table.concat(str2)
end
else
return basicSerialize(t)
end
end
return(_tb2st(t))
end
local serializeTableF = function(t) return tb2st_serialize(t,{pretty=true}) end --new serialization more compact
local function deepcopy(object)
local lookup_table = {}
local function _copy(object)
--assert(object~=REST)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
local function table_do_sorted(t,f)
local sorted = {}
for k,v in pairs(t) do
table.insert(sorted,k)
end
table.sort(sorted)
for ii,k in ipairs(sorted) do
f(k,t[k])
end
end
----------------------------
local function save_data(filename,...)
local file,err = io.open(filename,"w")
if not file then error(err) end
for i=1, select('#', ...) do
local data = select(i, ...)
file:write(data)
end
file:close()
end
local function read_data(filename)
local hfile,err = io.open(filename,"r")
if not hfile then error(err) end
local hstrfile = hfile:read"*a"
hfile:close()
return hstrfile
end
local function copyfile(src,dst,blocksize)
blocksize = blocksize or 1024*4
print( "copyfile", src, dst)
local srcf, err = io.open(src,"rb")
if not srcf then error(err) end
local dstf, err = io.open(dst,"wb")
if not dstf then error(err) end
while true do
local data = srcf:read(blocksize)
if not data then break end
dstf:write(data)
end
srcf:close()
dstf:close()
end
local function paramListWithoutDots(params)
local i, j = string.find(params, "%.%.%.")
while i > 1 do
i = i - 1
local c = string.sub(params,i,i)
if c == "," then
return string.sub(params, 1, i-1) .. params:sub(j+1)
elseif c == "(" then
return string.sub(params, 1, i) .. params:sub(j+1)
end
end
error("paramListWithoutDots failed")
return "()"
end
-------------------------------json saving
--avoid mixed tables (with string and integer keys)
local function json_prepare(defs)
--delete signatures in function
for k,def in pairs(defs) do
for k2,v in pairs(def) do
if type(k2)=="string" then
def[k2] = nil
end
end
end
return defs
end
local function save_output(self)
--add VARGS0
local defsVARG = {}
for k,defs in pairs(self.defsT) do
for i, def in ipairs(defs) do
if def.isvararg then
--print("vararg",k,#def)
local def1 = deepcopy(def)
def1.isvararg = nil
def1.isVARG0 = true
def1.argsT[#def1.argsT] = nil
def1.args = paramListWithoutDots(def1.args)
def1.call_args_old = paramListWithoutDots(def1.call_args_old)
def1.call_args = paramListWithoutDots(def1.call_args)
def1.signature = paramListWithoutDots(def1.signature)
def1.cimguiname = def1.cimguiname.."0"
def1.ov_cimguiname = def1.ov_cimguiname.."0"
defsVARG[k.."0"] = defsVARG[k.."0"] or {}
table.insert(defsVARG[k.."0"], def1)
end
end
end
for k,def in pairs(defsVARG) do
self.defsT[k] = def
end
--add manual not present in module
for k,v in pairs(self.manuals) do
if not self.defsT[k] then
--print("add manual",k)
self.defsT[k] = {v}
else
--print("skipped manual",k)
end
end
----------------------
save_data("./output/overloads.txt",self.overloadstxt)
save_data("./output/definitions.lua",serializeTableF(self.defsT))
save_data("./output/structs_and_enums.lua",serializeTableF(self.structs_and_enums_table))
save_data("./output/typedefs_dict.lua",serializeTableF(self.typedefs_dict))
save_data("./output/constants.lua",serializeTableF(self.constants))
local json = require"json"
local json_opts = {dict_on_empty={defaults=true}}
save_data("./output/definitions.json",json.encode(json_prepare(self.defsT),json_opts))
save_data("./output/structs_and_enums.json",json.encode(self.structs_and_enums_table))
save_data("./output/typedefs_dict.json",json.encode(self.typedefs_dict))
save_data("./output/constants.json",json.encode(self.constants))
local modulename = self.modulename
copyfile("./output/"..modulename..".h", "../"..modulename..".h")
copyfile("./output/"..modulename..".cpp", "../"..modulename..".cpp")
os.remove("./output/"..modulename..".h")
os.remove("./output/"..modulename..".cpp")
end
---------------------- C writing functions
local function func_header_generate_structs(FP)
local outtab = {}--"\n/////func_header_generate_structs\n"}
prtable("embeded_structs",FP.embeded_structs)
table_do_sorted(FP.embeded_structs,function(k,v)
if not FP.typenames[k] then
print("embeded",k,v)
table.insert(outtab,"typedef "..v.." "..k..";\n")
end
end)
table_do_sorted(FP.embeded_enums,function(k,v) table.insert(outtab,"typedef "..v.." "..k..";\n") end)
--table.insert(outtab, "\n//////////templates\n")
table_do_sorted(FP.templates,function(ttype,v)
--print("func_header_generate_structs",ttype)
if not (ttype == "std::function") then
table_do_sorted(v,function(ttypein,te)
local ttype2 = ttype:gsub("::","_") --std::string
table.insert(outtab,"typedef "..ttype.."<"..ttypein.."> "..ttype2.."_"..te..";\n")
end)
end
end)
--M.prtable("typenames",FP.typenames)
table_do_sorted(FP.opaque_structs,function(k,v)
if not FP.typenames[k] then
table.insert(outtab,"typedef "..v.." "..k..";\n")
--table.insert(outtab,"typedef const "..v.."* "..k.."_opq;\n")
--table.insert(outtab,"typedef "..v.."* "..k.."_opq;\n")
end
end)
--table.insert(outtab, "\n//////////end func header\n")
return outtab
end
local function func_header_generate_funcs(FP)
local outtab = {}
for _,t in ipairs(FP.funcdefs) do
if t.cimguiname then
local cimf = FP.defsT[t.cimguiname]
local def = cimf[t.signature]
assert(def,t.signature..t.cimguiname)
local custom
if FP.custom_header then
custom = FP.custom_header(outtab, def)
end
local manual = FP.get_manuals(def)
if not custom and not manual and not def.templated and not FP.get_skipped(def) --and not (FP.opaque_structs[def.stname] and not def.is_static_function)
then
local addcoment = "" --def.comment or ""
local empty = def.args:match("^%(%)") --no args
if def.constructor then
assert(def.stname ~= "","constructor without struct")
table.insert(outtab,"CIMGUI_API "..def.stname.."* "..def.ov_cimguiname ..(empty and "(void)" or def.args)..";"..addcoment.."\n")
if FP.CONSTRUCTORS_GENERATION then
outtab[#outtab] = outtab[#outtab].."\nCIMGUI_API void "..def.ov_cimguiname.."_Construct("..def.stname.."* self"..(empty and "" or ","..def.args:sub(2,-2))..");\n"
end
elseif def.destructor then
table.insert(outtab,"CIMGUI_API void "..def.ov_cimguiname..def.args..";"..addcoment.."\n")
else --not constructor
--local ret = FP.nP_ret[def.ret] or def.ret
local ret = def.ret
if def.stname == "" or def.is_static_function then --ImGui namespace or top level
table.insert(outtab,"CIMGUI_API "..ret.." ".. def.ov_cimguiname ..(empty and "(void)" or def.args)..";"..addcoment.."\n")
if def.isvararg then
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args)..";\n")
table.insert(outtab, "#endif\n")
end
else
table.insert(outtab,"CIMGUI_API "..ret.." "..def.ov_cimguiname..def.args..";"..addcoment.."\n")
if def.isvararg then
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args)..";\n")
table.insert(outtab, "#endif\n")
end
end
end
end
if FP.custom_function_post then
FP:custom_function_post(outtab, def)
end
else --not cimguiname
table.insert(outtab,t.comment:gsub("%%","%%%%").."\n")-- %% substitution for gsub
end
end
return outtab
end
local function func_header_generate(FP)
local outtab = func_header_generate_structs(FP)
table.insert(outtab, 1, "\n#ifndef CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n")
table.insert(outtab,"#endif //CIMGUI_DEFINE_ENUMS_AND_STRUCTS\n")
local outtabf = func_header_generate_funcs(FP)
outtabf = table.concat(outtabf)
assert(type(outtabf)=="string")
--outtabf = M.header_subs_nonPOD(FP,outtabf)
local cfuncsstr = table.concat(outtab)..outtabf
cfuncsstr = cfuncsstr:gsub("\n+","\n") --several empty lines to one empty line
return cfuncsstr
end
local function ImGui_f_implementation(def)
local outtab = {}
local ptret = def.retref and "&" or ""
table.insert(outtab,"CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname..def.args.."\n")
table.insert(outtab,"{\n")
local namespace = def.namespace and def.namespace.."::" or ""
--namespace = def.is_static_function and namespace..def.stname.."::" or namespace
if def.isvararg then
local call_args = def.call_args:gsub("%.%.%.","args")
table.insert(outtab," va_list args;\n")
table.insert(outtab," va_start(args, fmt);\n")
if def.ret~="void" then
table.insert(outtab," "..def.ret.." ret = "..namespace..def.funcname.."V"..call_args..";\n")
else
table.insert(outtab," "..namespace..def.funcname.."V"..call_args..";\n")
end
table.insert(outtab," va_end(args);\n")
if def.ret~="void" then
table.insert(outtab," return ret;\n")
end
table.insert(outtab,"}\n")
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args).."\n")
table.insert(outtab, "{\n")
local returnword = "return "
if def.ret=="void" then returnword = "" end
table.insert(outtab, " "..returnword..def.ov_cimguiname..paramListWithoutDots(def.call_args_old)..";\n")
table.insert(outtab, "}\n")
table.insert(outtab, "#endif\n")
elseif def.nonUDT then
if def.nonUDT == 1 then
--table.insert(outtab," *pOut = "..namespace..def.funcname..def.call_args..";\n")
insert(outtab," return ConvertFromCPP_"..def.conv.."("..namespace..def.funcname..def.call_args..");\n")
elseif def.nonUDT == 2 then
insert(outtab," return reinterpret_cast<"..def.ret..">("..ptret..namespace..def.funcname..def.call_args..");\n")
elseif def.nonUDT == "string" then
insert(outtab," static std::string str;\n")
insert(outtab," str.assign("..ptret.."self->"..def.funcname..def.call_args..");\n")
insert(outtab," return str.c_str();\n")
elseif def.nonUDT == "opaque" then
insert(outtab," static auto opq = "..ptret..namespace..def.funcname..def.call_args..";\n")
insert(outtab," opq = "..ptret..namespace..def.funcname..def.call_args..";\n")
insert(outtab," return &opq;\n")
end
table.insert(outtab,"}\n")
else --standard ImGui
table.insert(outtab," return "..ptret..namespace..def.funcname..def.call_args..";\n")
table.insert(outtab,"}\n")
end
--table.insert(outtab,"}\n")
return table.concat(outtab, "")
end
local function struct_f_implementation(def)
local outtab = {}
local empty = def.args:match("^%(%)") --no args
local ptret = def.retref and "&" or ""
local imgui_stname = def.stname
table.insert(outtab,"CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname..def.args.."\n")
table.insert(outtab,"{\n")
if def.isvararg then
local call_args = def.call_args:gsub("%.%.%.","args")
table.insert(outtab," va_list args;\n")
table.insert(outtab," va_start(args, fmt);\n")
if def.ret~="void" then
table.insert(outtab," "..def.ret.." ret = self->"..def.funcname.."V"..call_args..";\n")
else
table.insert(outtab," self->"..def.funcname.."V"..call_args..";\n")
end
table.insert(outtab," va_end(args);\n")
if def.ret~="void" then
table.insert(outtab," return ret;\n")
end
table.insert(outtab,"}\n")
-- For variadic functions we add a function implementation with zero argumets, for compatibility with languages such as C#.
table.insert(outtab, "#ifdef CIMGUI_VARGS0\n")
table.insert(outtab, "CIMGUI_API".." "..def.ret.." "..def.ov_cimguiname.."0"..paramListWithoutDots(def.args).."\n")
table.insert(outtab, "{\n")
local returnword = "return "
if def.ret=="void" then returnword = "" end
table.insert(outtab, " "..returnword..def.ov_cimguiname.."(self,"..paramListWithoutDots(def.call_args_old):sub(2,-1)..";\n")
table.insert(outtab, "}\n")
table.insert(outtab, "#endif\n")
elseif def.nonUDT then
if def.nonUDT == 1 then
--table.insert(outtab," *pOut = self->"..def.funcname..def.call_args..";\n")
--local typret = (def.ret):gsub("const ","")
insert(outtab," return ConvertFromCPP_"..def.conv.."(self->"..def.funcname..def.call_args..");\n")
elseif def.nonUDT == 2 then
insert(outtab," return reinterpret_cast<"..def.ret..">("..ptret.."self->"..def.funcname..def.call_args..");\n")
elseif def.nonUDT == "string" then
insert(outtab," static std::string str;\n")
insert(outtab," str.assign("..ptret.."self->"..def.funcname..def.call_args..");\n")
insert(outtab," return str.c_str();\n")
elseif def.nonUDT == "opaque" then
insert(outtab," static auto opq = "..ptret.."self->"..def.funcname..def.call_args..";\n")
insert(outtab," opq = "..ptret.."self->"..def.funcname..def.call_args..";\n")
insert(outtab," return &opq;\n")
end
table.insert(outtab,"}\n")
else --standard struct
table.insert(outtab," return "..ptret.."self->"..def.funcname..def.call_args..";\n")
table.insert(outtab,"}\n")
end
return table.concat(outtab, "")
end
local function func_implementation(FP)
local outtab = {}
for _,t in ipairs(FP.funcdefs) do
repeat -- continue simulation
if not t.cimguiname then break end
local cimf = FP.defsT[t.cimguiname]
local def = cimf[t.signature]
assert(def)
local custom
if FP.custom_implementation then
custom = FP.custom_implementation(outtab, def, FP)
end
local manual = FP.get_manuals(def)
if not custom and not manual and not def.templated and not FP.get_skipped(def) --and not (FP.opaque_structs[def.stname] and not def.is_static_function)
then
if def.constructor then
local tab = {}
assert(def.stname ~= "","constructor without struct")
local empty = def.args:match("^%(%)") --no args
table.insert(tab,"CIMGUI_API "..def.stname.."* "..def.ov_cimguiname..(empty and "(void)" or def.args).."\n")
table.insert(tab,"{\n")
table.insert(tab," return IM_NEW("..def.stname..")"..def.call_args..";\n")
table.insert(tab,"}\n")
if FP.CONSTRUCTORS_GENERATION then
table.insert(tab,"CIMGUI_API void "..def.ov_cimguiname.."_Construct("..def.stname.."* self"..(empty and "" or ","..def.args:sub(2,-2))..")\n")
table.insert(tab,"{\n")
table.insert(tab," IM_PLACEMENT_NEW(self)"..def.stname..def.call_args..";\n")
table.insert(tab,"}\n")
end
table.insert(outtab, table.concat(tab, ""))
elseif def.destructor then
local tab = {}
local args = "("..def.stname.."* self)"
local fname = def.stname.."_destroy"
table.insert(tab,"CIMGUI_API void "..fname..args.."\n")
table.insert(tab,"{\n")
table.insert(tab," IM_DELETE(self);\n")
table.insert(tab,"}\n")
table.insert(outtab, table.concat(tab, ""))
elseif def.stname == "" or def.is_static_function then
table.insert(outtab, ImGui_f_implementation(def))
else -- stname
table.insert(outtab, struct_f_implementation(def))
end
end
if FP.custom_function_post then
FP:custom_function_post(outtab, def)
end
until true
end
local conversors = FP:genConversors()
local cimplem = conversors .. table.concat(outtab)
return cimplem
end
return {func_implementation = func_implementation, save_output = save_output, save_data = save_data, read_data = read_data, copyfile = copyfile, func_header_generate = func_header_generate, prtable = prtable, table_do_sorted = table_do_sorted, save_output = save_output, deepcopy = deepcopy, serializeTableF = serializeTableF, func_header_generate_structs = func_header_generate_structs}