This commit is contained in:
Stefan Salewski 2021-02-17 09:20:35 +01:00
commit b82c02b2fc
4 changed files with 387 additions and 405 deletions

View file

@ -1,6 +1,6 @@
= High level GTK4 and GTK3 bindings for the Nim programming language = High level GTK4 and GTK3 bindings for the Nim programming language
//(c) Stefan Salewski //(c) Stefan Salewski
//Version 0.8.6 //Version 0.8.7
:experimental: :experimental:
:imagesdir: http://ssalewski.de/tmp :imagesdir: http://ssalewski.de/tmp
//:source-highlighter: pygments //:source-highlighter: pygments
@ -29,8 +29,16 @@ with code inserted from files directly.
NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers. NOTE: This work is partly based on earlier works of J. Mansour and has been supported by A. Rumpf, E. Bassi and other _Nim_ and _GTK/Gnome_ developers.
The `combinatorics` module was kindly provided by R. Behrends. The `combinatorics` module was kindly provided by R. Behrends.
NOTE: This is version 0.8.6 of the gintro Nim GTK bindings. NOTE: This is version 0.8.7 of the gintro Nim GTK bindings.
The package contains now all the standard gst modules, and due to a recent We did a larger internal cleanup for the gen.nim generator script but tried to
generate output modules identical to v.0.8.6 still. For next release v0.8.8
there will be some changes in the generated modules then.
Also for this version 0.8.7 we do support webkit2 for GTK4, and we have
fixed the newGFileTmp() issue, see https://github.com/StefanSalewski/gintro/issues/112.
NOTE: Version 0.8.6 of the gintro Nim GTK bindings
contains now all the standard gst modules, and due to a recent
request also the gtklayershell.nim module. Due to issues with some gst modules request also the gtklayershell.nim module. Due to issues with some gst modules
we do now call init() for the gst module before we use it with gobject-introspection. we do now call init() for the gst module before we use it with gobject-introspection.
We do the same for GTK3 and GTK4 as these provide also an init() proc. According to We do the same for GTK3 and GTK4 as these provide also an init() proc. According to

View file

@ -0,0 +1,20 @@
# https://wiki.gnome.org/Projects/WebKitGtk/ProgrammingGuide/Tutorial
# nim c --gc:arc webkitgtk.nim
import gintro/[gtk4, glib, gobject, gio, webkit25]
proc appActivate (app: Application) =
let window = newApplicationWindow(app)
window.title = "WebKitGtk"
window.defaultSize = (800, 600)
let view = newWebView()
view.loadUri("https://nim-lang.org/")
window.setChild(view)
window.show
proc main =
let app = newApplication("org.gtk.example")
connect(app, "activate", appActivate)
discard app.run
main()

View file

@ -1,6 +1,6 @@
# Package # Package
version = "0.8.6" version = "0.8.7"
author = "Stefan Salewski" author = "Stefan Salewski"
description = "High level GObject-Introspection based GTK3/GTK4 bindings" description = "High level GObject-Introspection based GTK3/GTK4 bindings"
license = "MIT" license = "MIT"

View file

@ -1,6 +1,6 @@
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language # High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
# nimpretty --maxLineLen:130 gen.nim # nimpretty --maxLineLen:130 gen.nim
# v 0.8.6 2021-JAN-28 # v 0.8.7 2021-FEB-16
# (c) S. Salewski 2018 # (c) S. Salewski 2018
# usefull for finding death code: # usefull for finding death code:
@ -38,6 +38,9 @@
# NOTE: Currently we support subclassing only for constructor functions like gtk_button_new() # NOTE: Currently we support subclassing only for constructor functions like gtk_button_new()
# CAUTION: some procs are advertised as constructor but do not construct new objects,
# they just return existing ones as gdk_cursor_new_from_name()
from os import `/`, paramCount from os import `/`, paramCount
import gir, gobject, glib import gir, gobject, glib
import strutils import strutils
@ -351,8 +354,10 @@ const someEvent: HashSet[string] = """"
proc fixedModName(s: string): string = proc fixedModName(s: string): string =
result = s result = s
if not ISGTK3 and (s == "gdk" or s == "gtk" or s == "gdkX11"): if not ISGTK3 and (s == "gdk" or s == "gtk" or s == "gdkx11"):
result &= "4" result &= "4"
if not ISGTK3 and (s == "javascriptcore" or s == "webkit2" or s == "webkit2webextension"):
result &= "5"
if not ISGTK3 and (s == "gtksource"): if not ISGTK3 and (s == "gtksource"):
result &= "5" result &= "5"
@ -1337,7 +1342,11 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
# see https://discourse.gnome.org/t/what-is-wrong-with-g-enum-complete-type-info-and/4489 # see https://discourse.gnome.org/t/what-is-wrong-with-g-enum-complete-type-info-and/4489
echo "Caution: No free/unref found for ", ' ', " (", sym, ')' echo "Caution: No free/unref found for ", ' ', " (", sym, ')'
else: else:
if gBaseInfoGetName(info) notin ["Variant", "VariantType"]: # seems for glib.GVariant we have to guess -- or maybe just know #if gBaseInfoGetName(info) notin ["Variant", "VariantType"]: # seems for glib.GVariant we have to guess -- or maybe just know
if gBaseInfoGetName(info) notin ["Variant", "VariantType"] and # looks ugly, so hide for v0.8.7, investigate later...
sym notin ["soup_xmlrpc_parse_request", "gst_audio_resampler_new", "gst_rtsp_connection_accept", "gst_rtsp_connection_create_from_socket", "gst_rtsp_connection_create", "gst_sdp_media_copy", "gst_sdp_media_new"]:
echo "Caution: Do guess free/unref for ", ' ', " (", sym, ')' echo "Caution: Do guess free/unref for ", ' ', " (", sym, ')'
if boxedFreeMeName == "gBoxedFreeGVariantType": # this does not work if boxedFreeMeName == "gBoxedFreeGVariantType": # this does not work
assert false assert false
@ -1354,6 +1363,97 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
freeMeName = "generic_" & $g_object_info_get_unref_function(parent) freeMeName = "generic_" & $g_object_info_get_unref_function(parent)
assert(freeMeName != "") assert(freeMeName != "")
template block8(prochead: string; errorcheckadd: bool): untyped =
if isProxyCandidateret2:
assert (gCallableInfoGetCallerOwns(minfo) in {GITransfer.NOTHING, GITransfer.EVERYTHING}) # both occur
if asym == "newFromStreamAsync" and sym.startsWith("gdk_pixbuf_animation_new"):
asym = "newAnimationFromStreamAsync"
if prochead.len == 0:
methodBuffer.writeLine("\nproc " & asym & EM & pars.plist & " =")
else:
methodBuffer.writeLine(prochead)
if not isProxyCandidateret2:
methodBuffer.write(pars.tempRes)
methodBuffer.write(pars.arrLex)
methodBuffer.write(sss)
var freeMeName{.inject.}: string
var boxedFreeMeName{.inject.}: string
for j in 0.cint ..< gCallableInfoGetNArgs(minfo):
freeMeName = ""
boxedFreeMeName = ""
let arg = gCallableInfoGetArg(minfo, j)
let t = gArgInfoGetType(arg)
var ngrt = newGenRec(t)
if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0):
if gArgInfoGetDirection(arg) == GIDirection.IN and gArgInfoGetOwnershipTransfer(arg) == GITransfer.EVERYTHING and
isProxyCandidate(t) and not callerAlloc.contains(ngrt.namePlainNS):
# like gtk_widget_add_controller()
let n = mangleName(gBaseInfoGetName(arg))
if gArgInfoMayBeNull(arg): # and prochead.len != 0: # wrong to be compatible with 0.8.6
methodBuffer.writeLine(" if " & n & " != nil:")
methodBuffer.writeLine(" " & n & ".ignoreFinalizer = true")
else:
methodBuffer.writeLine(" " & n & ".ignoreFinalizer = true")
if gArgInfoGetDirection(arg) == GIDirection.OUT and isProxyCandidate(t) and
not callerAlloc.contains(ngrt.namePlainNS) and not gArgInfoIsCallerAllocates(arg):
let tag = gTypeInfoGetTag(t)
assert(tag == GITypeTag.INTERFACE)
assert gArgInfoGetOwnershipTransfer(arg) != GITransfer.CONTAINER
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.EVERYTHING or
gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING: # pass always the same finalizer for ARC
let iface = gTypeInfoGetInterface(t)
if gBaseInfoGetType(iface) == GIInfoType.OBJECT:
let ttt = gArgInfoGetType(arg)
freeMeName = modPrefix(ttt, sym) & "finalizeGObject" # TODO: investigate, we may need the full toggleRef stuff!
else:
let info = iface
var freeMe{.inject.}: GIFunctionInfo
findFreeProc(info, gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING)
let h2 = mangleName(gBaseInfoGetName(arg))
if gArgInfoIsOptional(arg):
methodBuffer.writeLine(" if addr($2) != nil:" % [ngrt.namePlain, h2])
if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")")
else:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")")
else:
if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")")
else:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")")
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING:
if gArgInfoIsOptional(arg):
methodBuffer.writeLine(" if addr($2) != nil:" % [ngrt.namePlain, h2])
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true")
else:
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") # as we have always to attach one with ARC.
if gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" var gerror: ptr glib.Error")
if errorcheckadd:
pars.arglist.insert(", addr gerror", pars.arglist.high)
var multi = ""
for k, v in pars.replist:
if v[1].flags * {RecResFlag.namedA, cstringA} != {}:
assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" var $1x$2: array[$3, pointer]" % [StringArrayName, multi, $StringArrayEntries])
methodBuffer.writeLine(" var $1$2: cstringArray = cast[cstringArray](addr $1x$2)" % [StringArrayName, multi])
methodBuffer.writeLine(" var $1_00 = seq2$2($3, $4$5)" % [k.strip(chars = {'`'}), v[0].replace("00").capitalizeAscii, k,
StringArrayName, multi])
if multi == "":
multi = "1"
elif v[1].flags.contains(RecResFlag.unamedA):
assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" var $1_00: $2" % [k.strip(chars = {'`'}), v[1].name00])
else:
if v[1].optOut:
methodBuffer.writeLine(" var $1_00: $2" % [k.strip(chars = {'`'}), v[0], k])
else:
methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v[0], k])
# assert(info != nil) # why can it be nil? # assert(info != nil) # why can it be nil?
# if Lib.len == 0: # xlib, fontconfig, freetype2 # but Lib is local to main(), so let it crash # if Lib.len == 0: # xlib, fontconfig, freetype2 # but Lib is local to main(), so let it crash
# return # return
@ -1436,7 +1536,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
if sym == "nice_agent_get_selected_pair": return # was very wrong, fixed manually if sym == "nice_agent_get_selected_pair": return # was very wrong, fixed manually
if sym == "g_hash_table_destroy": return if sym == "g_hash_table_destroy": return
try: try:
pars = genPars(mInfo, false, info) pars = genPars(mInfo, false, info)
processedFunctions.incl(sym) processedFunctions.incl(sym)
@ -1548,11 +1647,12 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
#if sym == "pango_attr_background_new": echo "sss", info != nil, asym #if sym == "pango_attr_background_new": echo "sss", info != nil, asym
asym = fixedProcNames.getOrDefault(sym, asym) asym = fixedProcNames.getOrDefault(sym, asym)
# BLOCKMARK8 : 3 cases: constructor, isProxyCandidate(ret2), plain else # BLOCKMARK8 : 3 cases: constructor, isProxyCandidate(ret2), plain else
if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0: let isProxyCandidateret2 = isProxyCandidate(ret2)
assert pars.replist.len == 0 # ok it's a fact for constructors, so we don't have to generate code for it
for j in 0.cint ..< gCallableInfoGetNArgs(minfo): #else: # BLOCKMARK8 assert gerror
let arg = gCallableInfoGetArg(minfo, j) if not (isProxyCandidateret2 or isGObject):
assert gArgInfoGetDirection(arg) notin {GIDirection.OUT, INOUT} # so we can ignore this case! block8("", true)
if isProxyCandidateret2 or isGObject: # BLOCKMARK8
for itt in 0 .. 2: # generate the new(), the new(typedesc) and the init() proc for itt in 0 .. 2: # generate the new(), the new(typedesc) and the init() proc
var hhh = "\nproc " & asym & EM & pars.plist var hhh = "\nproc " & asym & EM & pars.plist
if itt == 1: # new(typedesc) if itt == 1: # new(typedesc)
@ -1568,399 +1668,242 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
# hhh = hhh.replace("new", "init") # hhh = hhh.replace("new", "init")
hhh = hhh.replace("proc new", "proc init") # v0.8.2 hhh = hhh.replace("proc new", "proc init") # v0.8.2
hhh = hhh.replace("*(", "*[T](result: var T" & semi) hhh = hhh.replace("*(", "*[T](result: var T" & semi)
if itt == 2: if itt == 2 and ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0):
depStr = " {.deprecated.}" depStr = " {.deprecated.}"
methodBuffer.writeLine(hhh & depStr & " =") if itt == 2 or ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0):
hhh = hhh & depStr & " ="
else:
hhh = hhh & " ="
block8(hhh, itt == 0)
if not isGObject: if not isGObject:
methodBuffer.write(pars.tempRes) # caution, gobjectTemp() may write tempRes too. methodBuffer.write(pars.tempRes) # caution, gobjectTemp() may write tempRes too.
methodBuffer.write(pars.arrLex)
methodBuffer.write(sss)
if gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" var gerror: ptr glib.Error")
if itt == 0: pars.arglist.insert(", addr gerror", pars.arglist.high)
if itt == 1 or itt == 2: if itt == 1 or itt == 2:
methodBuffer.writeLine(" assert(result is $1)" % [manglename(gBaseInfoGetName(info))]) methodBuffer.writeLine(" assert(result is $1)" % [manglename(gBaseInfoGetName(info))])
if isGObject: if isGObject:
# CAUTION: some procs are advertised as constructor but do not construct new objects,
# they just return existing ones as gdk_cursor_new_from_name()
gobjectTemp() gobjectTemp()
###if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0 and
### gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING:
### methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
elif gCallableInfoGetCallerOwns(minfo) == GITransfer.CONTAINER:
assert false
elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or
gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # and gBaseInfoGetName(info) == "Variant": gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for ARC we have always to use the same finalizer!
if false: #sym == "g_closure_new_simple": let tag = gTypeInfoGetTag(ret2)
let nMethods = gStructInfoGetNMethods(info) assert tag == GITypeTag.INTERFACE
for j in 0.cint ..< nMethods: var iface = gTypeInfoGetInterface(ret2)
echo "yes there is unref method! ", $gBaseInfoGetName(gStructInfoGetMethod(info, j)) if gBaseInfoGetType(iface) == GIInfoType.INTERFACE:
#assert(gStructInfoFindMethod(info, "unref") != nil) # TODO GI bug? gobjectTemp()
assert info != nil
var freeMe: GIFunctionInfo
var freeMeName: string
var boxedFreeMeName: string
findFreeProc(info, gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" let impl0 = " & sym & pars.arglist) # fast return in case of error
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if impl0.isNil:")
methodBuffer.writeLine(" return nil")
#if sym == "g_closure_new_simple" or sym == "g_closure_new_object":
# freeMeName = "unref" # TODO GI bug?
#assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
if false: #i > 0: # with ARC we have no finalizer support for user defined subclasses, so we have to leak mem!
methodBuffer.writeLine(" new(result)")
elif boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName)
elif freeMeName == "":
assert false
methodBuffer.writeLine(" new(result)")
else: else:
methodBuffer.writeLine(" fnew(result, $1)" % freeMeName) assert(gBaseInfoGetType(iface) in {GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.OBJECT})
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo): var freeMeName: string
methodBuffer.writeLine(" result.impl = impl0") var freeMe: GIFunctionInfo
else: var boxedFreeMeName: string
methodBuffer.writeLine(" result.impl = " & sym & pars.arglist) findFreeProc(iface, gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING)
if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0 and if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo):
gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING) or methodBuffer.writeLine(" let impl0 = " & sym & pars.arglist) # fast return in case of error
((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0 and checkForGerror()
gBaseInfoGetName(info) == "Variant"): if gCallableInfoMayReturnNull(minfo):
assert((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0) methodBuffer.writeLine(" if impl0.isNil:")
methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC. methodBuffer.writeLine(" return nil")
else:
assert false
for k, v in pars.replist:
assert false
if false: #gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" if gerror != nil:")
methodBuffer.writeLine(" let msg = $gerror.message")
methodBuffer.writeLine(" g_error_free(gerror[])")
methodBuffer.writeLine(" raise newException(GException, msg)")
# end of for itt in 0 .. 2:
elif isProxyCandidate(ret2): # BLOCKMARK8
assert (gCallableInfoGetCallerOwns(minfo) in {GITransfer.NOTHING, GITransfer.EVERYTHING}) # both occur
methodBuffer.writeLine("\nproc " & asym & EM & pars.plist & " =")
methodBuffer.write(pars.arrLex)
methodBuffer.write(sss)
if gCallableInfoCanThrowGerror(minfo):
methodBuffer.writeLine(" var gerror: ptr glib.Error")
pars.arglist.insert(", addr gerror", pars.arglist.high)
for k, v in pars.replist:
methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v[0], k])
if isGObject:
gobjectTemp()
elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or
gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for ARC we have always to use the same finalizer!
let tag = gTypeInfoGetTag(ret2)
assert tag == GITypeTag.INTERFACE
var iface = gTypeInfoGetInterface(ret2)
if gBaseInfoGetType(iface) == GIInfoType.INTERFACE:
gobjectTemp()
else:
assert(gBaseInfoGetType(iface) in {GIInfoType.STRUCT, GIInfoType.UNION, GIInfoType.OBJECT})
var freeMeName: string
var freeMe: GIFunctionInfo
var boxedFreeMeName: string
findFreeProc(iface, gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" let impl0 = " & sym & pars.arglist) # fast return in case of error
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if impl0.isNil:")
methodBuffer.writeLine(" return nil")
if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName)
elif freeMeName == "":
# assert false # TODO we have to fix this case manually
# echo "xCaution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')' # check this from time to time!
methodBuffer.writeLine(" new(result)")
else:
methodBuffer.writeLine(" fnew(result, $1)" % freeMeName)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" result.impl = impl0")
else:
methodBuffer.writeLine(" result.impl = " & sym & pars.arglist)
if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for the none gobjects
methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
elif false: #else:
assert gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING
methodBuffer.writeLine(" new(result)")
methodBuffer.writeLine(" result.impl = " & sym & pars.arglist)
for k, v in pars.replist:
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
else: # BLOCKMARK8
if asym == "newFromStreamAsync" and sym.startsWith("gdk_pixbuf_animation_new"):
asym = "newAnimationFromStreamAsync"
methodBuffer.writeLine("\nproc " & asym & EM & pars.plist & " =")
methodBuffer.write(pars.tempRes)
methodBuffer.write(pars.arrLex)
methodBuffer.write(sss)
var freeMeName: string
var boxedFreeMeName: string
for j in 0.cint ..< gCallableInfoGetNArgs(minfo):
freeMeName = ""
boxedFreeMeName = ""
let arg = gCallableInfoGetArg(minfo, j)
let t = gArgInfoGetType(arg)
var ngrt = newGenRec(t)
if gArgInfoGetDirection(arg) == GIDirection.IN and gArgInfoGetOwnershipTransfer(arg) == GITransfer.EVERYTHING and
isProxyCandidate(t) and not callerAlloc.contains(ngrt.namePlainNS):
# like gtk_widget_add_controller()
let n = mangleName(gBaseInfoGetName(arg))
if gArgInfoMayBeNull(arg):
methodBuffer.writeLine(" if " & n & " != nil:")
methodBuffer.writeLine(" " & n & ".ignoreFinalizer = true")
else:
methodBuffer.writeLine(" " & n & ".ignoreFinalizer = true")
if gArgInfoGetDirection(arg) == GIDirection.OUT and isProxyCandidate(t) and
not callerAlloc.contains(ngrt.namePlainNS) and not gArgInfoIsCallerAllocates(arg):
let tag = gTypeInfoGetTag(t)
assert(tag == GITypeTag.INTERFACE)
assert gArgInfoGetOwnershipTransfer(arg) != GITransfer.CONTAINER
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.EVERYTHING or
gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING: # pass always the same finalizer for ARC
let iface = gTypeInfoGetInterface(t)
if gBaseInfoGetType(iface) == GIInfoType.OBJECT:
let ttt = gArgInfoGetType(arg)
freeMeName = modPrefix(ttt, sym) & "finalizeGObject" # TODO: investigate, we may need the full toggleRef stuff!
else:
let info = iface
var freeMe: GIFunctionInfo
findFreeProc(info, gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING)
let h2 = mangleName(gBaseInfoGetName(arg))
if gArgInfoIsOptional(arg):
#methodBuffer.writeLine(" if cast[ptr $1]($2) != nil:" % [ngrt.namePlain, h2])
methodBuffer.writeLine(" if addr($2) != nil:" % [ngrt.namePlain, h2])
if boxedFreeMeName != "": if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")") methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName)
elif freeMeName == "": elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")") # assert false # TODO we have to fix this case manually
# echo "xCaution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')' # check this from time to time!
methodBuffer.writeLine(" new(result)")
else: else:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")") methodBuffer.writeLine(" fnew(result, $1)" % freeMeName)
else: if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo):
if boxedFreeMeName != "": methodBuffer.writeLine(" result.impl = impl0")
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")")
else: else:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")") methodBuffer.writeLine(" result.impl = " & sym & pars.arglist)
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING: if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for the none gobjects
if gArgInfoIsOptional(arg): if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0):
methodBuffer.writeLine(" if addr($2) != nil:" % [ngrt.namePlain, h2]) methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") else: assert false
else: if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0 and gBaseInfoGetName(info) == "Variant"):
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") # as we have always to attach one with ARC. methodBuffer.writeLine(" result.ignoreFinalizer = true")
if gCallableInfoCanThrowGerror(minfo): if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0:
methodBuffer.writeLine(" var gerror: ptr glib.Error") break
pars.arglist.insert(", addr gerror", pars.arglist.high) elif ngrRet.res == glist:
var multi = "" var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING
for k, v in pars.replist: if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) !=
if v[1].flags * {RecResFlag.namedA, cstringA} != {}: GITransfer.NOTHING:
assert v[1].flags.contains(RecResFlag.array) methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
#assert not (v[1].flags.contains(RecResFlag.zeroTerminated))
methodBuffer.writeLine(" var $1x$2: array[$3, pointer]" % [StringArrayName, multi, $StringArrayEntries])
methodBuffer.writeLine(" var $1$2: cstringArray = cast[cstringArray](addr $1x$2)" % [StringArrayName, multi])
methodBuffer.writeLine(" var $1_00 = seq2$2($3, $4$5)" % [k.strip(chars = {'`'}), v[0].replace("00").capitalizeAscii, k,
StringArrayName, multi])
if multi == "":
multi = "1"
elif v[1].flags.contains(RecResFlag.unamedA):
assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" var $1_00: $2" % [k.strip(chars = {'`'}), v[1].name00])
else:
if v[1].optOut:
methodBuffer.writeLine(" var $1_00: $2" % [k.strip(chars = {'`'}), v[0], k])
else:
methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v[0], k])
if ngrRet.res == glist:
var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) !=
GITransfer.NOTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
methodBuffer.writeLine(" result = glistObjects2seq($1, resul0, $2)" % [ngrRet.childName, $elTransferFull])
if ngrRet.infoType == GIInfoType.STRUCT:
if gBaseInfoGetName(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))) notin ["Atom", "Variant", "TimedValue"]: # care later
methodBuffer.writeLine(" result = glistStructs2seq[$1](resul0, $2)" % [ngrRet.childName, $(
gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING)])
# caution TimedValue is a "light" entity, so we need a different glistStructs2seq() for that!
if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING:
methodBuffer.writeLine(" g_list_free(resul0)") # only free the list itself, the elements are moved to the seq
else:
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
if ngrRet.infoType != GIInfoType.INTERFACE:
assert findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))).len == 0
methodBuffer.writeLine(" result = glistObjects2seq($1, $2, $3)" % [ngrRet.childName, sym & pars.arglist,
$elTransferFull])
else:
methodBuffer.writeLine(" discard")
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
elif ngrRet.res == gslist:
var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) !=
GITransfer.NOTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
methodBuffer.writeLine(" result = gslistObjects2seq($1, resul0, $2)" % [ngrRet.childName, $elTransferFull])
if ngrRet.infoType == GIInfoType.STRUCT:
if gBaseInfoGetName(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))) notin ["Atom", "Variant"]: # care later
methodBuffer.writeLine(" result = gslistStructs2seq[$1](resul0, $2)" % [ngrRet.childName, $(
gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING)])
if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING:
methodBuffer.writeLine(" g_slist_free(resul0)") # only free the list itself, the elements are moved to the seq
else:
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
if ngrRet.infoType != GIInfoType.INTERFACE:
assert findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))).len == 0
methodBuffer.writeLine(" result = gslistObjects2seq($1, $2, $3)" % [ngrRet.childName, sym & pars.arglist,
$elTransferFull])
else:
methodBuffer.writeLine(" discard")
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intAX:
# https://discourse.gnome.org/t/g-key-file-get-integer-list-transfer-container/4729
# for fundamental types GITransfer.EVERYTHING and GITransfer.CONTAINER are equivalent
var co = gCallableInfoGetCallerOwns(minfo)
assert ngrRet.flags.contains(RecResFlag.array)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or co in {GITransfer.EVERYTHING, CONTAINER}:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $1ToSeq(resul0, $2.int)" % [fixedName2(ngrRet.name00), pars.blex])
else:
methodBuffer.writeLine(" result = $1ToSeq($3, $2.int)" % [fixedName2(ngrRet.name00), pars.blex, sym & pars.arglist])
assert(co in {GITransfer.EVERYTHING, CONTAINER, NOTHING})
if co in {GITransfer.EVERYTHING, CONTAINER}:
methodBuffer.writeLine(" cogfree(resul0)")
elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intA0:
assert ngrRet.flags.contains(RecResFlag.array)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $1ZT2seq(resul0)" % [unCaped(fixedName2(ngrRet.name))])
else:
methodBuffer.writeLine(" result = $1ZT2seq($2)" % [unCaped(fixedName2(ngrRet.name)), sym & pars.arglist])
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
methodBuffer.writeLine(" cogfree(resul0)")
elif isString(ret2):
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $resul0")
else:
methodBuffer.writeLine(" result = $" & sym & pars.arglist)
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
methodBuffer.writeLine(" cogfree(resul0)")
elif RecResFlag.namedA in ngrRet.flags:
assert ngrRet.flags.contains(RecResFlag.array)
let h = ngrRet.name00
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $1ToSeq(resul0, $2_00.int)" % [fixedName2(h.replace("00")).unCap, pars.blex])
else:
methodBuffer.writeLine(" result = $1ToSeq($3, $2_00.int)" % [fixedName2(h.replace("00")).unCap, pars.blex, sym & pars.arglist])
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
methodBuffer.writeLine(" cogfree(resul0)")
elif (pars.replist.len > 0 or gCallableInfoCanThrowGerror(minfo)) and ngrRet.name != "void":
# caution dragons like g_key_file_get_locale_string_list()
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
discard # echo "Untamed dragon: ", sym
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.write(" result = ")
if needTypeConv(ngrRet.name, ngrRet):
methodBuffer.writeLine(doCt3nt(ngrRet.name, ngrRet) & '(' & "resul0" & ')')
else:
methodBuffer.writeLine("resul0")
else:
methodBuffer.write(" result = ")
if needTypeConv(ngrRet.name, ngrRet):
methodBuffer.writeLine(doCt3nt(ngrRet.name, ngrRet) & '(' & sym & pars.arglist & ')')
else:
methodBuffer.writeLine(sym & pars.arglist)
elif needTypeConv(ngrRet.name, ngrRet):
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
if ngrRet.name == "ptr cstring" and ngrRet.flags.contains(RecResFlag.array) and gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" result = cstringArrayToSeq(resul0)")
methodBuffer.writeLine(" g_strfreev(resul0)")
else:
methodBuffer.writeLine(" " & doCt3nt(ngrRet.name, ngrRet) & '(' & "resul0" & ')')
else:
if pars.tempResFree != "": # ugly, do we have a better test for this case
#if ngrRet.name != "void":
methodBuffer.writeLine(" result = " & doCt3nt(ngrRet.name, ngrRet) & '(' & sym & pars.arglist & ')')
else:
methodBuffer.writeLine(" " & doCt3nt(ngrRet.name, ngrRet) & '(' & sym & pars.arglist & ')')
checkForGerror() # i.e. for nice_agent_set_remote_candidates, free GSList
else:
if gCallableInfoCanThrowGerror(minfo) and ngrRet.name != "void":
assert false
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
else:
methodBuffer.writeLine(" " & sym & pars.arglist)
checkForGerror() checkForGerror()
if gCallableInfoCanThrowGerror(minfo) and ngrRet.name != "void": if gCallableInfoMayReturnNull(minfo):
assert false methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" resul0 #####") methodBuffer.writeLine(" return")
for k, v in pars.replist: if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
if v[1].flags.contains(RecResFlag.unamedA): methodBuffer.writeLine(" result = glistObjects2seq($1, resul0, $2)" % [ngrRet.childName, $elTransferFull])
assert v[1].flags.contains(RecResFlag.array) if ngrRet.infoType == GIInfoType.STRUCT:
methodBuffer.writeLine(" $1.setLen($2)" % [k, pars.blex]) if gBaseInfoGetName(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))) notin ["Atom", "Variant", "TimedValue"]: # care later
methodBuffer.writeLine(" copyMem(unsafeaddr $1[0], $1_00, $2.int * sizeof($1[0]))" % [k.strip(chars = {'`'}), pars.blex]) methodBuffer.writeLine(" result = glistStructs2seq[$1](resul0, $2)" % [ngrRet.childName, $(
methodBuffer.writeLine(" cogfree($1_00)" % [k.strip(chars = {'`'})]) gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING)])
elif RecResFlag.namedA in v[1].flags: # caution TimedValue is a "light" entity, so we need a different glistStructs2seq() for that!
assert v[1].flags.contains(RecResFlag.array) if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING:
methodBuffer.writeLine(" $1 = $2($3_00, $4)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'}), pars.blex]) methodBuffer.writeLine(" g_list_free(resul0)") # only free the list itself, the elements are moved to the seq
else:
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
if ngrRet.infoType != GIInfoType.INTERFACE:
assert findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))).len == 0
methodBuffer.writeLine(" result = glistObjects2seq($1, $2, $3)" % [ngrRet.childName, sym & pars.arglist,
$elTransferFull])
else: else:
if v[1].optOut: methodBuffer.writeLine(" discard")
methodBuffer.writeLine(" if $1.addr != nil:" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})]) assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})]) elif ngrRet.res == gslist:
else: var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})]) if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) !=
# BLOCKMARK8 GITransfer.NOTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
methodBuffer.writeLine(" result = gslistObjects2seq($1, resul0, $2)" % [ngrRet.childName, $elTransferFull])
if ngrRet.infoType == GIInfoType.STRUCT:
if gBaseInfoGetName(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))) notin ["Atom", "Variant"]: # care later
methodBuffer.writeLine(" result = gslistStructs2seq[$1](resul0, $2)" % [ngrRet.childName, $(
gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING)])
if gCallableInfoGetCallerOwns(minfo) != GITransfer.NOTHING:
methodBuffer.writeLine(" g_slist_free(resul0)") # only free the list itself, the elements are moved to the seq
else:
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
if ngrRet.infoType != GIInfoType.INTERFACE:
assert findFreeObject(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))).len == 0
methodBuffer.writeLine(" result = gslistObjects2seq($1, $2, $3)" % [ngrRet.childName, sym & pars.arglist,
$elTransferFull])
else:
methodBuffer.writeLine(" discard")
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intAX:
# https://discourse.gnome.org/t/g-key-file-get-integer-list-transfer-container/4729
# for fundamental types GITransfer.EVERYTHING and GITransfer.CONTAINER are equivalent
var co = gCallableInfoGetCallerOwns(minfo)
assert ngrRet.flags.contains(RecResFlag.array)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or co in {GITransfer.EVERYTHING, CONTAINER}:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $1ToSeq(resul0, $2.int)" % [fixedName2(ngrRet.name00), pars.blex])
else:
methodBuffer.writeLine(" result = $1ToSeq($3, $2.int)" % [fixedName2(ngrRet.name00), pars.blex, sym & pars.arglist])
assert(co in {GITransfer.EVERYTHING, CONTAINER, NOTHING})
if co in {GITransfer.EVERYTHING, CONTAINER}:
methodBuffer.writeLine(" cogfree(resul0)")
elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intA0:
assert ngrRet.flags.contains(RecResFlag.array)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $1ZT2seq(resul0)" % [unCaped(fixedName2(ngrRet.name))])
else:
methodBuffer.writeLine(" result = $1ZT2seq($2)" % [unCaped(fixedName2(ngrRet.name)), sym & pars.arglist])
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
methodBuffer.writeLine(" cogfree(resul0)")
elif isString(ret2):
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $resul0")
else:
methodBuffer.writeLine(" result = $" & sym & pars.arglist)
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
methodBuffer.writeLine(" cogfree(resul0)")
elif RecResFlag.namedA in ngrRet.flags:
assert ngrRet.flags.contains(RecResFlag.array)
let h = ngrRet.name00
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.writeLine(" result = $1ToSeq(resul0, $2_00.int)" % [fixedName2(h.replace("00")).unCap, pars.blex])
else:
methodBuffer.writeLine(" result = $1ToSeq($3, $2_00.int)" % [fixedName2(h.replace("00")).unCap, pars.blex, sym & pars.arglist])
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
methodBuffer.writeLine(" cogfree(resul0)")
elif (pars.replist.len > 0 or gCallableInfoCanThrowGerror(minfo)) and ngrRet.name != "void":
# caution dragons like g_key_file_get_locale_string_list()
if gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING:
discard # echo "Untamed dragon: ", sym
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
methodBuffer.write(" result = ")
if needTypeConv(ngrRet.name, ngrRet):
methodBuffer.writeLine(doCt3nt(ngrRet.name, ngrRet) & '(' & "resul0" & ')')
else:
methodBuffer.writeLine("resul0")
else:
methodBuffer.write(" result = ")
if needTypeConv(ngrRet.name, ngrRet):
methodBuffer.writeLine(doCt3nt(ngrRet.name, ngrRet) & '(' & sym & pars.arglist & ')')
else:
methodBuffer.writeLine(sym & pars.arglist)
elif needTypeConv(ngrRet.name, ngrRet):
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
checkForGerror()
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if resul0.isNil:")
methodBuffer.writeLine(" return")
if ngrRet.name == "ptr cstring" and ngrRet.flags.contains(RecResFlag.array) and gCallableInfoGetCallerOwns(minfo) ==
GITransfer.EVERYTHING:
methodBuffer.writeLine(" result = cstringArrayToSeq(resul0)")
methodBuffer.writeLine(" g_strfreev(resul0)")
else:
methodBuffer.writeLine(" " & doCt3nt(ngrRet.name, ngrRet) & '(' & "resul0" & ')')
else:
if pars.tempResFree != "": # ugly, do we have a better test for this case
#if ngrRet.name != "void":
methodBuffer.writeLine(" result = " & doCt3nt(ngrRet.name, ngrRet) & '(' & sym & pars.arglist & ')')
else:
methodBuffer.writeLine(" " & doCt3nt(ngrRet.name, ngrRet) & '(' & sym & pars.arglist & ')')
checkForGerror() # i.e. for nice_agent_set_remote_candidates, free GSList
else:
if gCallableInfoCanThrowGerror(minfo) and ngrRet.name != "void":
assert false
methodBuffer.writeLine(" let resul0 = " & sym & pars.arglist)
else:
methodBuffer.writeLine(" " & sym & pars.arglist)
checkForGerror()
if gCallableInfoCanThrowGerror(minfo) and ngrRet.name != "void":
assert false
methodBuffer.writeLine(" resul0 #####")
for k, v in pars.replist:
if v[1].flags.contains(RecResFlag.unamedA):
assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" $1.setLen($2)" % [k, pars.blex])
methodBuffer.writeLine(" copyMem(unsafeaddr $1[0], $1_00, $2.int * sizeof($1[0]))" % [k.strip(chars = {'`'}), pars.blex])
methodBuffer.writeLine(" cogfree($1_00)" % [k.strip(chars = {'`'})])
elif RecResFlag.namedA in v[1].flags:
assert v[1].flags.contains(RecResFlag.array)
methodBuffer.writeLine(" $1 = $2($3_00, $4)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'}), pars.blex])
else:
if v[1].optOut:
methodBuffer.writeLine(" if $1.addr != nil:" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
else:
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})])
# BLOCKMARK8
else: # } end of large proxy block BLOCK7 else: # } end of large proxy block BLOCK7
asym = fixedProcNames.getOrDefault(sym, asym) asym = fixedProcNames.getOrDefault(sym, asym)
pars = genPars(mInfo, false, info) pars = genPars(mInfo, false, info)
@ -1970,7 +1913,8 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
if info != nil and (gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT) and if info != nil and (gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT) and
gCallableInfoGetNArgs(minfo) == (if gCallableInfoIsMethod(minfo): 0 else: 1): gCallableInfoGetNArgs(minfo) == (if gCallableInfoIsMethod(minfo): 0 else: 1):
#if not callerAlloc.contains(modulenamespace & '.' & $gBaseInfoGetName(info)) and (asym == "free" or asym == "unref"): #if not callerAlloc.contains(modulenamespace & '.' & $gBaseInfoGetName(info)) and (asym == "free" or asym == "unref"):
if not callerAlloc.contains(modulenamespace & '.' & $gBaseInfoGetName(info)) and (asym == "free" or asym == "unref" or asym == "destroy"): # v0.8.6 if not callerAlloc.contains(modulenamespace & '.' & $gBaseInfoGetName(info)) and (asym == "free" or asym == "unref" or
asym == "destroy"): # v0.8.6
methodBuffer.writeLine("\nproc finalizer" & asym & EM & "(self: $1) =" % [$gBaseInfoGetName(info)]) methodBuffer.writeLine("\nproc finalizer" & asym & EM & "(self: $1) =" % [$gBaseInfoGetName(info)])
methodBuffer.writeLine(" if not self.ignoreFinalizer:") methodBuffer.writeLine(" if not self.ignoreFinalizer:")
if gTypeInfoGetTag(ret2) != GITypeTag.VOID: # i.e. gst_sdp_media_free() if gTypeInfoGetTag(ret2) != GITypeTag.VOID: # i.e. gst_sdp_media_free()
@ -2764,7 +2708,8 @@ proc processInfo(i: GIBaseInfo) =
elif gBaseInfoGetType(i) == GIInfoType.CONSTANT: elif gBaseInfoGetType(i) == GIInfoType.CONSTANT:
writeConst(i) writeConst(i)
elif gBaseInfoGetType(i) == GIInfoType.Boxed: elif gBaseInfoGetType(i) == GIInfoType.Boxed:
echo "gBaseInfoGetType(i) == GIInfoType.Boxed: ", gBaseInfoGetName(i) if $gBaseInfoGetName(i) notin ["TreeRowData", "ByteArray", "FileList"]: # hide ugly output for v0.8.7, investgate later
echo "gBaseInfoGetType(i) == GIInfoType.Boxed: ", gBaseInfoGetName(i)
# echo "++++++++ ", g_registered_type_info_get_g_type(i), g_registered_type_info_get_type_name(i) # echo "++++++++ ", g_registered_type_info_get_g_type(i), g_registered_type_info_get_type_name(i)
# assert false executed for gtk4 # assert false executed for gtk4
else: else:
@ -3245,7 +3190,6 @@ proc main(namespace: string; version: cstring = nil) =
if namespace == "Gtk" and version == "4.0" and gtk4Lib == nil: if namespace == "Gtk" and version == "4.0" and gtk4Lib == nil:
gtk4Lib = tryInitGtk4() gtk4Lib = tryInitGtk4()
let typelib = gi.gIrepositoryRequire(namespace, version, cast[GIRepositoryLoadFlags](0), error) let typelib = gi.gIrepositoryRequire(namespace, version, cast[GIRepositoryLoadFlags](0), error)
#let typelib = gIrepositoryRequirePrivate(nil, namespace, "/usr/lib/girepository-1.0", version, cast[GIRepositoryLoadFlags](0), error) #let typelib = gIrepositoryRequirePrivate(nil, namespace, "/usr/lib/girepository-1.0", version, cast[GIRepositoryLoadFlags](0), error)
if typelib.isNil: if typelib.isNil:
@ -3259,7 +3203,7 @@ proc main(namespace: string; version: cstring = nil) =
var weImportGObject = false var weImportGObject = false
output.writeLine("# dependencies:") output.writeLine("# dependencies:")
var importedModules = "" var importedModules = ""
for j in 0 .. 12: for j in 0 .. 18: # stupid restriction!
if dep[j].isNil: break if dep[j].isNil: break
if j == 0: if j == 0:
importedModules = "import " importedModules = "import "
@ -3828,6 +3772,13 @@ proc get$1*(builder: Builder; name: string): $1 =
suff = "4" suff = "4"
if namespace == "GtkSource" and version == nil: if namespace == "GtkSource" and version == nil:
suff = "5" suff = "5"
if namespace in ["JavaScriptCore", "WebKit2", "WebKit2WebExtension"]:
if version == "4.0":
suff = ""
if version == "5.0":
suff = "5"
var o = open("nim_gi" / (namespace.toLowerAscii) & suff & ".nim", fmWrite) var o = open("nim_gi" / (namespace.toLowerAscii) & suff & ".nim", fmWrite)
o.write(output.data) o.write(output.data)
o.close() o.close()
@ -3887,10 +3838,10 @@ proc launch() =
main("Handy") main("Handy")
main("Nice") main("Nice")
main("cairo") main("cairo")
main("WebKit2") main("WebKit2", "4.0")
main("JavaScriptCore") main("JavaScriptCore", "4.0")
main("Soup") main("Soup")
main("WebKit2WebExtension") main("WebKit2WebExtension", "4.0")
main("Gst") main("Gst")
main("GstBase") main("GstBase")
main("GstAllocators") main("GstAllocators")
@ -3940,6 +3891,10 @@ proc launch() =
# main("Handy") # not yet available for GTK4 # main("Handy") # not yet available for GTK4
main("Nice") main("Nice")
main("cairo") main("cairo")
main("WebKit2", "5.0")
main("JavaScriptCore", "5.0")
main("Soup")
main("WebKit2WebExtension", "5.0")
main("Gst") main("Gst")
main("GstBase") main("GstBase")
main("GstAllocators") main("GstAllocators")
@ -3993,7 +3948,7 @@ launch()
# if not xcallerAlloc.contains(el): # if not xcallerAlloc.contains(el):
# echo el # echo el
# 3996 lines # 3951 lines
# gtk_icon_view_get_tooltip_context bug Candidate # gtk_icon_view_get_tooltip_context bug Candidate
# gtk_tree_view_get_cursor bug # gtk_tree_view_get_cursor bug
# #
@ -4010,4 +3965,3 @@ proc gst_structure_take(oldstrPtr: var ptr Structure00; newstr: ptr Structure00)
proc take*(oldstrPtr: var Structure; newstr: Structure = nil): bool = proc take*(oldstrPtr: var Structure; newstr: Structure = nil): bool =
toBool(gst_structure_take(if oldstrPtr.isNil: nil else: cast[ptr Structure00](oldstrPtr.impl), if newstr.isNil: nil else: cast[ptr Structure00](newstr.impl))) toBool(gst_structure_take(if oldstrPtr.isNil: nil else: cast[ptr Structure00](oldstrPtr.impl), if newstr.isNil: nil else: cast[ptr Structure00](newstr.impl)))
]# ]#