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
//(c) Stefan Salewski
//Version 0.8.6
//Version 0.8.7
:experimental:
:imagesdir: http://ssalewski.de/tmp
//: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.
The `combinatorics` module was kindly provided by R. Behrends.
NOTE: This is version 0.8.6 of the gintro Nim GTK bindings.
The package contains now all the standard gst modules, and due to a recent
NOTE: This is version 0.8.7 of the gintro Nim GTK bindings.
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
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

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
version = "0.8.6"
version = "0.8.7"
author = "Stefan Salewski"
description = "High level GObject-Introspection based GTK3/GTK4 bindings"
license = "MIT"

View file

@ -1,6 +1,6 @@
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
# nimpretty --maxLineLen:130 gen.nim
# v 0.8.6 2021-JAN-28
# v 0.8.7 2021-FEB-16
# (c) S. Salewski 2018
# usefull for finding death code:
@ -38,6 +38,9 @@
# 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
import gir, gobject, glib
import strutils
@ -351,8 +354,10 @@ const someEvent: HashSet[string] = """"
proc fixedModName(s: string): string =
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"
if not ISGTK3 and (s == "javascriptcore" or s == "webkit2" or s == "webkit2webextension"):
result &= "5"
if not ISGTK3 and (s == "gtksource"):
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
echo "Caution: No free/unref found for ", ' ', " (", sym, ')'
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, ')'
if boxedFreeMeName == "gBoxedFreeGVariantType": # this does not work
assert false
@ -1354,6 +1363,97 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
freeMeName = "generic_" & $g_object_info_get_unref_function(parent)
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?
# if Lib.len == 0: # xlib, fontconfig, freetype2 # but Lib is local to main(), so let it crash
# 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 == "g_hash_table_destroy": return
try:
pars = genPars(mInfo, false, info)
processedFunctions.incl(sym)
@ -1548,11 +1647,12 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
#if sym == "pango_attr_background_new": echo "sss", info != nil, asym
asym = fixedProcNames.getOrDefault(sym, asym)
# BLOCKMARK8 : 3 cases: constructor, isProxyCandidate(ret2), plain else
if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0:
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):
let arg = gCallableInfoGetArg(minfo, j)
assert gArgInfoGetDirection(arg) notin {GIDirection.OUT, INOUT} # so we can ignore this case!
let isProxyCandidateret2 = isProxyCandidate(ret2)
#else: # BLOCKMARK8 assert gerror
if not (isProxyCandidateret2 or isGObject):
block8("", true)
if isProxyCandidateret2 or isGObject: # BLOCKMARK8
for itt in 0 .. 2: # generate the new(), the new(typedesc) and the init() proc
var hhh = "\nproc " & asym & EM & pars.plist
if itt == 1: # new(typedesc)
@ -1568,399 +1668,242 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
# hhh = hhh.replace("new", "init")
hhh = hhh.replace("proc new", "proc init") # v0.8.2
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.}"
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:
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:
methodBuffer.writeLine(" assert(result is $1)" % [manglename(gBaseInfoGetName(info))])
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()
###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
gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # and gBaseInfoGetName(info) == "Variant":
if false: #sym == "g_closure_new_simple":
let nMethods = gStructInfoGetNMethods(info)
for j in 0.cint ..< nMethods:
echo "yes there is unref method! ", $gBaseInfoGetName(gStructInfoGetMethod(info, j))
#assert(gStructInfoFindMethod(info, "unref") != nil) # TODO GI bug?
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)")
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:
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 ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0 and
gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING) or
((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0 and
gBaseInfoGetName(info) == "Variant"):
assert((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0)
methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
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])
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(" & h2 & ", " & boxedFreeMeName & ")")
methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName)
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:
methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")")
else:
if boxedFreeMeName != "":
methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")")
methodBuffer.writeLine(" fnew(result, $1)" % freeMeName)
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" result.impl = impl0")
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")
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)
#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)
methodBuffer.writeLine(" result.impl = " & sym & pars.arglist)
if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for the none gobjects
if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0):
methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
else: assert false
if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0 and gBaseInfoGetName(info) == "Variant"):
methodBuffer.writeLine(" result.ignoreFinalizer = true")
if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0:
break
elif 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 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])
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:
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
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()
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
asym = fixedProcNames.getOrDefault(sym, asym)
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
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" 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(" if not self.ignoreFinalizer:")
if gTypeInfoGetTag(ret2) != GITypeTag.VOID: # i.e. gst_sdp_media_free()
@ -2764,7 +2708,8 @@ proc processInfo(i: GIBaseInfo) =
elif gBaseInfoGetType(i) == GIInfoType.CONSTANT:
writeConst(i)
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)
# assert false executed for gtk4
else:
@ -3245,7 +3190,6 @@ proc main(namespace: string; version: cstring = nil) =
if namespace == "Gtk" and version == "4.0" and gtk4Lib == nil:
gtk4Lib = tryInitGtk4()
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)
if typelib.isNil:
@ -3259,7 +3203,7 @@ proc main(namespace: string; version: cstring = nil) =
var weImportGObject = false
output.writeLine("# dependencies:")
var importedModules = ""
for j in 0 .. 12:
for j in 0 .. 18: # stupid restriction!
if dep[j].isNil: break
if j == 0:
importedModules = "import "
@ -3828,6 +3772,13 @@ proc get$1*(builder: Builder; name: string): $1 =
suff = "4"
if namespace == "GtkSource" and version == nil:
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)
o.write(output.data)
o.close()
@ -3887,10 +3838,10 @@ proc launch() =
main("Handy")
main("Nice")
main("cairo")
main("WebKit2")
main("JavaScriptCore")
main("WebKit2", "4.0")
main("JavaScriptCore", "4.0")
main("Soup")
main("WebKit2WebExtension")
main("WebKit2WebExtension", "4.0")
main("Gst")
main("GstBase")
main("GstAllocators")
@ -3940,6 +3891,10 @@ proc launch() =
# main("Handy") # not yet available for GTK4
main("Nice")
main("cairo")
main("WebKit2", "5.0")
main("JavaScriptCore", "5.0")
main("Soup")
main("WebKit2WebExtension", "5.0")
main("Gst")
main("GstBase")
main("GstAllocators")
@ -3993,7 +3948,7 @@ launch()
# if not xcallerAlloc.contains(el):
# echo el
# 3996 lines
# 3951 lines
# gtk_icon_view_get_tooltip_context bug Candidate
# 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 =
toBool(gst_structure_take(if oldstrPtr.isNil: nil else: cast[ptr Structure00](oldstrPtr.impl), if newstr.isNil: nil else: cast[ptr Structure00](newstr.impl)))
]#