cpp2ffi.lua: imgui-nodes-editor work 1

This commit is contained in:
sonoro1234
2026-04-25 08:45:55 +02:00
parent ad70f13873
commit 0313c558fc
2 changed files with 184 additions and 111 deletions

View File

@@ -473,7 +473,7 @@ local function parseItems(txt,linenumdict, itparent, dumpit)
else
error"no linenumdict"
end
table.insert(itemarr,{re_name=re_name,item=item,locat=loca,prevcomments=comments})
table.insert(itemarr,{re_name=re_name,item=item,locat=loca,prevcomments=comments,parent=itparent})
items[re_name] = items[re_name] or {}
table.insert(items[re_name],item)
end
@@ -1449,8 +1449,15 @@ local function ADDnonUDT(FP)
def.ret = "const char*"
def.nonUDT = "string"
elseif FP.opaque_structs[rets] then
assert(def.ret:match"%*","opaque struct without pointer")
def.ret = def.ret:gsub(rets.."%s*%*",rets.."_opq")
if not def.ret:match"%*" then
--assert(def.ret:match"%*","return opaque struct without pointer")
--M.prtable(def)
--error"return opaque struct without pointer"
def.nonUDT = "opaque"
def.ret = def.ret:gsub(rets,rets.."_opq")
else
def.ret = def.ret:gsub(rets.."%s*%*",rets.."_opq")
end
elseif def.stdret then -- not std::string
skip = true
end
@@ -1492,13 +1499,18 @@ local function ADDnonUDT(FP)
elseif FP.opaque_structs[typ2] then
--assert(v.type:match"%*","opaque struct arg without pointer")
if not v.type:match"%*" then
M.prtable(def)
error"opaque struct arg without pointer"
--M.prtable(def)
--error"opaque struct arg without pointer"
local newt = v.type:gsub(typ2,typ2.."_opq")
local callname = "*"..name
caar = caar .. callname .. ","
asp = asp .. newt.." "..name .. ","
else
local newt = v.type:gsub(typ2.."%s*%*",typ2.."_opq")
local callname = v.reftoptr and "*"..name or name
caar = caar .. callname .. ","
asp = asp .. newt.." "..name .. ","
end
local newt = v.type:gsub(typ2.."%s*%*",typ2.."_opq")
local callname = v.reftoptr and "*"..name or name
caar = caar .. callname .. ","
asp = asp .. newt.." "..name .. ","
else
local siz = v.type:match("(%[%d*%])") or ""
local typ = v.type:gsub("(%[%d*%])","")
@@ -1760,8 +1772,13 @@ function M.Parser()
table.insert(cdefs,{line:gsub("^(%s*.-)%s*$", "%1"),loca})
end
function par.getCname(stname,funcname, namespace)
if #stname == 0 then return funcname end --top level
local pre = stname.."_"
--if #stname == 0 then return funcname end --top level
local pre = (namespace and namespace~="") and (namespace:gsub("::","_") .. "_") or ""
pre = pre .. (stname~="" and (stname .. "_") or "")
if pre:match":" then print(stname, funcname, namespace); error"debug" end
-- if stname== "" then
-- local pre = (stname == "") and (namespace and (namespace.."_") or "") or stname.."_"
-- local pre = stname.."_"
return pre..funcname
end
function par.getCname_overload(stname,funcname,signature, namespace)
@@ -1881,11 +1898,44 @@ function M.Parser()
end
return stname, derived
end
local function get_parents_name(it)
local parnam = ""
while it.parent do
parnam = it.parent.name.."::"..parnam
it = it.parent
end
return parnam
end
local function get_parents_nameC(it)
local parnam = ""
while it.parent do
parnam = it.parent.name.."::"..parnam
it = it.parent
end
if parnam~="" then parnam = parnam:sub(1,-3) end
return parnam
end
--recursive item parsing
function par:parseItemsR2(txt, itparent)
local itsarr,its = parseItems(txt,self.linenumdict,itparent)
--clean protect
if itparent and itparent.re_name == "class_re" then
local first_private
for j,child in ipairs(itsarr) do
if child.item:match("^\n*%s*private:") or child.item:match("^\n*%s*protected:") then
first_private = j
break
end
end
if first_private then
for j=first_private,#itsarr do
--print("private discards",it.childs[j].re_name,it.childs[j].name)
itsarr[j] = nil
end
end
end
for i,it in ipairs(itsarr) do
--clean class
--clean class and get name
if it.re_name == "class_re" then
it.name = it.item:match("class%s+(%S+)")
print("cleaning class",it.name)
@@ -1893,17 +1943,21 @@ function M.Parser()
--it.item = it.item:gsub("private:","")
it.item = it.item:gsub("public:","")
it.item = it.item:gsub("enum%s*class","enum")
elseif it.re_name == "struct_re" then
it.name = it.item:match("struct%s+([^%s{]+)")
elseif it.re_name == "namespace_re" then
it.name = it.item:match("namespace%s+(%S+)")
end
if not isLeaf(it.re_name) then
local inner = strip_end(it.item:match("%b{}"):sub(2,-2))
--print(it.item)
--print("not isLeaf",it.re_name,it.name)
--print(inner)
it.childs = par:parseItemsR2(inner, it)
--if it.name == "TextEditor" then M.prtable(it.childs) end
for j,child in ipairs(it.childs) do
child.parent = it
end
-- for j,child in ipairs(it.childs) do
-- child.parent = it
-- end
if it.re_name == "struct_re" then
local typename = it.item:match("^%s*template%s*<%s*typename%s*(%S+)%s*>")
@@ -1920,37 +1974,57 @@ function M.Parser()
self.typenames[stname] = typename or templa2
end
elseif it.re_name == "namespace_re" then
it.name = it.item:match("namespace%s+(%S+)")
--it.name = it.item:match("namespace%s+(%S+)")
elseif it.re_name == "class_re" then
--it.name = it.item:match("class%s+(%S+)")
local first_private
for j,child in ipairs(it.childs) do
if child.item:match("^\n*%s*private:") or child.item:match("^\n*%s*protected:") then
first_private = j
break
end
end
if first_private then
for j=first_private,#it.childs do
--print("private discards",it.childs[j].re_name,it.childs[j].name)
it.childs[j] = nil
end
end
-- local first_private
-- for j,child in ipairs(it.childs) do
-- if child.item:match("^\n*%s*private:") or child.item:match("^\n*%s*protected:") then
-- first_private = j
-- break
-- end
-- end
-- if first_private then
-- for j=first_private,#it.childs do
----print("private discards",it.childs[j].re_name,it.childs[j].name)
-- it.childs[j] = nil
-- end
-- end
end
--create opaque_struct
if it.re_name == "struct_re" or it.re_name == "class_re" then
local stname,derived = derived_check(it)
if derived then
local derived2 = derived:gsub("%b<>","")
derived2 = derived2:gsub("%w+::","")
print("--derived check",stname, derived, derived2)
M.prtable(self.opaque_structs)
if self.opaque_structs[derived2] then
print("--make opaque opaque derived",it.name,derived,derived2)
it.opaque_struct = get_parents_name(it)..it.name
self.opaque_structs[it.name] = it.opaque_struct
end
end
if derived and derived:match"std::" then
print("--make opaque std::derived",it.name,derived)
it.opaque_struct = (itparent and itparent.name .."::" or "")..it.name
--it.opaque_struct = (itparent and itparent.name .."::" or "")..it.name
it.opaque_struct = get_parents_name(it)..it.name
self.opaque_structs[it.name] = it.opaque_struct
end
for j,child in ipairs(it.childs) do
-- if child.re_name == "vardef_re" and child.item:match"using" then
-- print("=====using",child.item)
-- end
if child.re_name == "vardef_re" and child.item:match"std::" then
print("--make opaque",it.name,child.item)
it.opaque_struct = (itparent and itparent.name .."::" or "")..it.name
--M.prtable(itparent)
--it.opaque_struct = (itparent and itparent.name .."::" or "")..it.name
it.opaque_struct = get_parents_name(it)..it.name
print("===parents1",get_parents_name(it),"===parents2",(itparent and itparent.name .."::" or ""))
print("===",it.opaque_struct)
--cant do that as function is recursive
--self.opaque_structs[it.name] = (itparent and itparent.name .."::" or "")..it.name
--self.opaque_structs[it.name] = get_parents_name(it)..it.name--(itparent and itparent.name .."::" or "")..it.name
self.opaque_structs[it.name] = it.opaque_struct
break
end
end
@@ -2172,6 +2246,15 @@ function M.Parser()
predeclare = predeclare .. templatetypedef
end
end
--clean using
if it.re_name == "vardef_re" and it.item:match("using%s+([^=%s]+)%s*=%s*([^;]+);") then
print("===using",it.item)
local typedef, assign = it2:match("using%s+([^=%s]+)%s*=%s*([^;]+);")
print(typedef,assign)
assign = assign:gsub("%w+::","")
predeclare = predeclare .. "\ntypedef "..assign.." "..typedef..";"
it2 = "" --"\ntypedef "..assign.." "..typedef..";"
end
--clean mutable
it2 = it2:gsub("mutable","")
--clean namespaces but not std::
@@ -2244,38 +2327,31 @@ function M.Parser()
end
return table.concat(outtab,""),stname,outtab,commtab, predeclare
end
local function get_parents_name(it)
local parnam = ""
while it.parent do
parnam = it.parent.name.."::"..parnam
it = it.parent
end
return parnam
end
local function get_parents_nameC(it)
local parnam = ""
while it.parent do
parnam = it.parent.name.."::"..parnam
it = it.parent
end
if parnam~="" then parnam = parnam:sub(1,-3) end
return parnam
end
function par:header_text_insert(tab,txt,it)
--print("--header_text_insert",txt)--:sub(1,40))
table.insert(tab, txt)
end
local function function_parse(self,it)
--print"------------function_parse"
local stname = ""
local namespace
if it.parent then
-- local parr = it.parent
-- it.parent = nil
-- print(parr.re_name,parr.name)
-- M.prtable(it)
-- it.parent = parr
if it.parent.re_name == "struct_re" or it.parent.re_name == "typedef_st_re" or it.parent.re_name == "class_re" then
stname = it.parent.name
namespace = get_parents_nameC(it)
elseif it.parent.re_name == "namespace_re" then
namespace = get_parents_nameC(it) --it.parent.name
--print("--function_parse namespace",namespace)
end
end
--print("--namespace",namespace)
--if namespace == "ax::NodeEditor::Config" then error"debug" end
if it.item:match"^%s*template%s+<" then
local ttype,fun = it.item:match"^%s*template%s+<%s*typename%s+([^>]+)%s*>%s*(.+)$"
if self.ftemplate_list and self.ftemplate_list[ttype] then
@@ -2292,7 +2368,8 @@ function M.Parser()
end
function par:enum_for_header( it,outtab)
--local enumname, enumbody = it.item:match"^%s*enum%s+([^%s;{}]+)[%s\n\r]*(%b{})"
local enumname = it.item:match"^%s*enum%s+([^%s;{}]+)"
local enumname = it.item:match"^%s*enum%s+([^%s;{}:]+)"
--if enumname and enumname:match":" then print("---enumname",enumname); error"debug" end
if enumname then
--if it's an enum with int type changed
if self.structs_and_enums_table.enumtypes[enumname] then
@@ -2318,12 +2395,14 @@ function M.Parser()
self:header_text_insert(outtab, it2, it)
end
if it.parent then
if it.parent.re_name == "namespace_re" then
local namespace = it.parent.item:match("namespace%s+(%S+)")
self.embeded_enums[enumname] = namespace.."::"..enumname
else
self.embeded_enums[enumname] = it.parent.name.."::"..enumname
end
local namespace = get_parents_nameC(it)
self.embeded_enums[enumname] = namespace.."::"..enumname
-- if it.parent.re_name == "namespace_re" then
-- local namespace = it.parent.item:match("namespace%s+(%S+)")
-- self.embeded_enums[enumname] = namespace.."::"..enumname
-- else
--self.embeded_enums[enumname] = it.parent.name.."::"..enumname
-- end
end
else --unamed enum just repeat declaration
local cl_item = clean_comments(it.item)
@@ -2388,14 +2467,22 @@ function M.Parser()
print("--skip extern vardef declaration:",it2)
it2 = ""
end
if it2:match("using") then
local typedef, assign = it2:match("using%s+([^=%s]+)%s*=%s*([^;]+);")
print("====using",string.format("%q %q",typedef, assign))
if assign and assign:match"%(%s*%*%s*%)" then --function typedef
it2 = "\ntypedef "..assign:gsub("%(%s*%*%s*%)","(*"..typedef..")")..";"
end
end
end
--table.insert(outtabpre,it2)
--table.insert(outtab,it2)
self:header_text_insert(outtab, it2, it)
-- add typedef after struct name
if it.re_name == "vardef_re" and it.item:match"^%s*struct" then
--print("---------emmbed")
--M.prtable(it)
-- print("---------emmbed")
-- print(it.item, it.locat)
-- error"debug"
local stname = it.item:match("struct%s*(%S+)%s*;")
--table.insert(typedefs_table,"typedef struct "..stname.." "..stname..";\n")
local tst = "\ntypedef struct "..stname.." "..stname..";"
@@ -2416,48 +2503,7 @@ function M.Parser()
--self:header_text_insert(outtab, predec .. cleanst, it)
self:enum_for_header(it,outtab)
end
--[[
--local enumname, enumbody = it.item:match"^%s*enum%s+([^%s;{}]+)[%s\n\r]*(%b{})"
local enumname = it.item:match"^%s*enum%s+([^%s;{}]+)"
if enumname then
--if it's an enum with int type changed
if self.structs_and_enums_table.enumtypes[enumname] then
local enumtype = self.structs_and_enums_table.enumtypes[enumname]
local enumbody = ""
local extraenums = ""
for i,v in ipairs(self.structs_and_enums_table.enums[enumname]) do
if type(v.calc_value)=="string" then
extraenums = extraenums .."\nstatic const "..enumtype.." "..v.name.." = "..v.calc_value..";"
else
enumbody = enumbody .. "\n" ..v.name .."="..v.value..","
end
end
enumbody = "{"..enumbody.."\n}"
--table.insert(outtab,"\ntypedef enum ".. enumbody..enumname..";"..extraenums)
local it2 = "\ntypedef enum ".. enumbody..enumname..";"..extraenums
self:header_text_insert(outtab, it2, it)
else
local enumbody = it.item:match"(%b{})"
enumbody = clean_comments(enumbody)
--table.insert(outtab,"\ntypedef enum ".. enumbody..enumname..";")
local it2 = "\ntypedef enum ".. enumbody..enumname..";"
self:header_text_insert(outtab, it2, it)
end
if it.parent then
if it.parent.re_name == "namespace_re" then
local namespace = it.parent.item:match("namespace%s+(%S+)")
self.embeded_enums[enumname] = namespace.."::"..enumname
else
self.embeded_enums[enumname] = it.parent.name.."::"..enumname
end
end
else --unamed enum just repeat declaration
local cl_item = clean_comments(it.item)
--table.insert(outtab,cl_item)
self:header_text_insert(outtab, cl_item, it)
print("unnamed enum",cl_item)
end
--]]
elseif it.re_name == "struct_re" or it.re_name == "typedef_st_re" or it.re_name == "class_re" then
if it.opaque_struct then
self:header_text_insert(outtab, "\ntypedef struct "..it.name.."* "..it.name.."_opq;\n",it)
@@ -2544,6 +2590,7 @@ function M.Parser()
end
local functype_re = "^%s*[%w%s%*]+%(%*[%w_]+%)%([^%(%)]*%)"
local functype_reex = "^(%s*[%w%s%*]+%(%*)([%w_]+)(%)%([^%(%)]*%))"
if line=="" then table.insert(outtab,{type="nil",name="nil"}) ;return end
line = clean_spaces(line)
if line:match(functype_re) then
local t1,name,t2 = line:match(functype_reex)
@@ -2583,10 +2630,12 @@ function M.Parser()
end
end
end
local unnamed_enum_counter = 0
local function enums_for_table(it, outtab, enumsordered)
--local enumname = it.item:match"^%s*enum%s+([^%s;{}]+)"
local enumname = it.item:match"^[^;{}]-enum%s+([^%s;{}]+)"
--local enumname = it.item:match"^[^;{}]-enum%s+([^%s;{}]+)"
local enumname = it.item:match"^%s*enum%s+([^%s;{}:]+)"
if not enumname then
unnamed_enum_counter = unnamed_enum_counter + 1
enumname = "unnamed"..unnamed_enum_counter
@@ -2728,7 +2777,9 @@ function M.Parser()
-- print(it.item)
-- M.prtable(outtab.structs[structname])
-- end
else
else --self.typenames[structname]
M.prtable("--self.typenames",structname,self.typenames[structname])
M.prtable("strtab 3, -1",strtab)
--templated struct
if structname then
print("saving templated struct",structname)
@@ -2738,7 +2789,7 @@ function M.Parser()
self:parse_struct_line(strtab[j],self.templated_structs[structname],comstab[j])
end
end
--M.prtable(self.templated_structs[structname])
M.prtable("--template_structs",structname,self.templated_structs[structname])
else
print("skipped unnamed struct",structname)
end
@@ -2833,6 +2884,7 @@ function M.Parser()
table.insert(strt,"----------------overloadings---------------------------")
--require"anima.utils"
M.table_do_sorted(self.defsT, function(k,v)
if k:match":" then error(k) end
get_types(v)
if #v > 1 then
numoverloaded = numoverloaded + #v
@@ -3048,9 +3100,11 @@ function M.Parser()
function par:cimgui_generation( cimgui_header)
local name = self.modulename
local hstrfile = read_data("./"..name.."_template.h")
M.prtable("templates",self.templates)
M.prtable("typenames",self.typenames)
local outpre,outpost = self.structs_and_enums[1], self.structs_and_enums[2]
local tdt = self:generate_templates()
M.prtable("generate_templates",tdt)
local cstructsstr = outpre..tdt..outpost
hstrfile = hstrfile:gsub([[#include "imgui_structs%.h"]],cstructsstr)
@@ -3380,10 +3434,13 @@ local function ImGui_f_implementation(def)
elseif def.nonUDT == "string" then
insert(outtab," static std::string str = "..ptret..namespace..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," 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," return "..ptret..(def.conv or "")..namespace..def.funcname..def.call_args..";\n")
table.insert(outtab,"}\n")
end
--table.insert(outtab,"}\n")
@@ -3421,6 +3478,9 @@ local function struct_f_implementation(def)
elseif def.nonUDT == "string" then
insert(outtab," static std::string str = "..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," return &opq;\n")
end
else --standard struct
table.insert(outtab," return "..ptret.."self->"..def.funcname..def.call_args..";\n")
@@ -3503,7 +3563,10 @@ local function func_header_generate_structs(FP)
local outtab = {} --"\n/////func_header_generate_structs\n"}
table_do_sorted(FP.embeded_structs,function(k,v)
table.insert(outtab,"typedef "..v.." "..k..";\n")
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)
@@ -3517,9 +3580,12 @@ local function func_header_generate_structs(FP)
end)
end
end)
--M.prtable(FP.typenames)
table_do_sorted(FP.opaque_structs,function(k,v)
table.insert(outtab,"typedef const "..v.."* "..k.."_opq;\n")
if not FP.typenames[k] then
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

View File

@@ -286,6 +286,7 @@ local function cimgui_generation(parser)
local tdt = parser:generate_templates()
cpp2ffi.prtable("generate_templates",tdt)
local cstructsstr = outpre..tdt..outpost
if gdefines.IMGUI_HAS_DOCK then
@@ -456,7 +457,11 @@ if ff then
else
backends_folder = IMGUI_PATH .. "/backends/"
end
local function getCname(stname,funcname, namespace)
if #stname == 0 then return funcname end --top level
local pre = stname.."_"
return pre..funcname
end
local parser2
if #implementations > 0 then
@@ -488,9 +493,11 @@ if #implementations > 0 then
end
end
parser2.cimgui_inherited = dofile([[./output/structs_and_enums.lua]])
parser2.getCname = getCname
local defines = parser2:take_lines(CPRE..extra_defines..extra_includes..source, {locati}, COMPILER)
local parser3 = cpp2ffi.Parser()
parser3.getCname = getCname
parser3.cimgui_inherited = dofile([[./output/structs_and_enums.lua]])
parser3:take_lines(CPRE..extra_defines..extra_includes..source, {locati}, COMPILER)
parser3:do_parse()