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,87 +1668,17 @@ 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:
# 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)")
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: if isGObject:
gobjectTemp() gobjectTemp()
elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or
@ -1683,98 +1713,14 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
else: else:
methodBuffer.writeLine(" result.impl = " & sym & pars.arglist) methodBuffer.writeLine(" result.impl = " & sym & pars.arglist)
if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for the none gobjects 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. methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
elif false: #else: else: assert false
assert gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING if ((gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) != 0 and gBaseInfoGetName(info) == "Variant"):
methodBuffer.writeLine(" new(result)") methodBuffer.writeLine(" result.ignoreFinalizer = true")
methodBuffer.writeLine(" result.impl = " & sym & pars.arglist) if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0:
for k, v in pars.replist: break
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, doCt3nt(v[0], v[1]), k.strip(chars = {'`'})]) elif ngrRet.res == glist:
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 != "":
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")
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 var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) != if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) !=
GITransfer.NOTHING: GITransfer.NOTHING:
@ -1786,7 +1732,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE: if ngrRet.infoType == GIInfoType.OBJECT or ngrRet.infoType == GIInfoType.INTERFACE:
methodBuffer.writeLine(" result = glistObjects2seq($1, resul0, $2)" % [ngrRet.childName, $elTransferFull]) methodBuffer.writeLine(" result = glistObjects2seq($1, resul0, $2)" % [ngrRet.childName, $elTransferFull])
if ngrRet.infoType == GIInfoType.STRUCT: if ngrRet.infoType == GIInfoType.STRUCT:
if gBaseInfoGetName(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))) notin ["Atom", "Variant", "TimedValue"]: # care later if gBaseInfoGetName(gTypeInfoGetInterface(gTypeInfoGetParamType(ret2, 0))) notin ["Atom", "Variant", "TimedValue"]: # care later
methodBuffer.writeLine(" result = glistStructs2seq[$1](resul0, $2)" % [ngrRet.childName, $( methodBuffer.writeLine(" result = glistStructs2seq[$1](resul0, $2)" % [ngrRet.childName, $(
gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING)]) gCallableInfoGetCallerOwns(minfo) != GITransfer.EVERYTHING)])
@ -1802,7 +1747,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
else: else:
methodBuffer.writeLine(" discard") methodBuffer.writeLine(" discard")
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER}) assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
elif ngrRet.res == gslist: elif ngrRet.res == gslist:
var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING var elTransferFull = gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING
if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) != if gCallableInfoCanThrowGerror(minfo) or gCallableInfoMayReturnNull(minfo) or gCallableInfoGetCallerOwns(minfo) !=
@ -1829,7 +1773,6 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
else: else:
methodBuffer.writeLine(" discard") methodBuffer.writeLine(" discard")
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER}) assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING, GITransfer.CONTAINER})
elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intAX: elif ngrRet.flags.contains(RecResFlag.unamedA) and ngrRet.res == intAX:
# https://discourse.gnome.org/t/g-key-file-get-integer-list-transfer-container/4729 # https://discourse.gnome.org/t/g-key-file-get-integer-list-transfer-container/4729
# for fundamental types GITransfer.EVERYTHING and GITransfer.CONTAINER are equivalent # for fundamental types GITransfer.EVERYTHING and GITransfer.CONTAINER are equivalent
@ -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,6 +2708,7 @@ 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:
if $gBaseInfoGetName(i) notin ["TreeRowData", "ByteArray", "FileList"]: # hide ugly output for v0.8.7, investgate later
echo "gBaseInfoGetType(i) == GIInfoType.Boxed: ", gBaseInfoGetName(i) 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
@ -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)))
]# ]#