full destructor support for ARC

This commit is contained in:
Stefan Salewski 2020-02-20 21:04:50 +01:00
commit ec7b8a7760
7 changed files with 330 additions and 131 deletions

View file

@ -1,6 +1,6 @@
= High level GTK3 (and GTK4) bindings for the Nim programming language = High level GTK3 (and GTK4) bindings for the Nim programming language
(c) Stefan Salewski (c) Stefan Salewski
//Version 0.6.1 //Version 0.7.1
:experimental: :experimental:
:imagesdir: http://ssalewski.de/tmp :imagesdir: http://ssalewski.de/tmp
:source-highlighter: pygments :source-highlighter: pygments
@ -25,8 +25,15 @@ 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: Starting with version v0.7.1 we have added destructor support when compiled with `--gc:arc`,
so we have no memory leak for subclassed objects any more, see the example in `Subclassing` section.
When compiled with default (refc) GC finalizers are used as before. And for objects marked with `nullable`
tag in gobject-introspection we now return nil value for the proxy object when the C lib has returned NULL.
So according to the C API docs, you can check for nil result for the few functions which may return NULL.
Nil objects returned by GTK Builder causes now a program termination (by assert()) because in that case
nil should indicate a programming error.
NOTE: Starting with current version v0.7.0 we support the new Nim memory management called ARC, see NOTE: Starting with version v0.7.0 we support the new Nim memory management called ARC, see
https://forum.nim-lang.org/t/5734. Just compile your programs with `--gc:arc`. The main advantage is that https://forum.nim-lang.org/t/5734. Just compile your programs with `--gc:arc`. The main advantage is that
ARC is deterministic, so it is easier to find bugs in the bindings or in your programs. And ARC is deterministic, so it is easier to find bugs in the bindings or in your programs. And
manually freeing resources, as we did previous for some cairo data structures to free them manually freeing resources, as we did previous for some cairo data structures to free them
@ -601,6 +608,14 @@ done separately by the user. The following code shows a GTK button, which is
extended with a counter member field. That counter is decreased for extended with a counter member field. That counter is decreased for
each button click. The amount of decrease (5) is passed to the callback as a int parameter. each button click. The amount of decrease (5) is passed to the callback as a int parameter.
Since gintro version 0.7.1 we support destructors when compile option `--gc:arc` is used.
To destroy subclassed widgets we have to create a `=destroy()` proc as shown in the code below.
This may look a bit verbose, and it is only necessary to avoid memory leaks for widgets
which are created and destroyed multiple times during program execution. Most widgets are
created at startup and live until program terminates, so there is no noticeable leak even
without a matching destroy. (In `examples/gtk3` there is a extended file called `subclassArcDestructorTest.nim`
to test the destructor behaviour.)
[[count_button.nim]] [[count_button.nim]]
[source,nim] [source,nim]
.count_button.nim .count_button.nim
@ -612,6 +627,10 @@ type
CountButton = ref object of Button CountButton = ref object of Button
counter: int counter: int
when compileOption("gc", "arc"):
proc `=destroy`(x: var typeof(CountButton()[])) =
gtk.`=destroy`(typeof(Button()[])(x))
proc buttonClicked (button: CountButton; decrement: int) = proc buttonClicked (button: CountButton; decrement: int) =
dec(button.counter, decrement) dec(button.counter, decrement)
button.label = "Counter: " & $button.counter button.label = "Counter: " & $button.counter

View file

@ -5,6 +5,10 @@ type
CountButton = ref object of Button CountButton = ref object of Button
counter: int counter: int
when compileOption("gc", "arc"):
proc `=destroy`(x: var typeof(CountButton()[])) =
gtk.`=destroy`(typeof(Button()[])(x))
proc buttonClicked (button: CountButton; decrement: int) = proc buttonClicked (button: CountButton; decrement: int) =
dec(button.counter, decrement) dec(button.counter, decrement)
button.label = "Counter: " & $button.counter button.label = "Counter: " & $button.counter

View file

@ -0,0 +1,37 @@
# nim c --gc:arc count_button.nim
import gintro/[gtk, glib, gobject, gio]
type
CountButton = ref object of Button
counter: int
when compileOption("gc", "arc"):
proc `=destroy`(x: var typeof(CountButton()[])) =
echo "CountButtonDestroy"
echo cast[CountButton](addr(x)).label # really ugly, only for test
gtk.`=destroy`(typeof(Button()[])(x))
proc buttonClicked (button: CountButton; decrement: int) =
dec(button.counter, decrement)
button.label = "Counter: " & $button.counter
echo "Counter is now: ", button.counter
proc appActivate (app: Application) =
var button, d: CountButton
let window = newApplicationWindow(app)
window.title = "Count Button"
initButton(button, "Counting down from 100 by 5")
initButton(d, "Dummy Button") # to test call of destroy
echo d.getLabel
button.counter = 100
window.add(button)
button.connect("clicked", buttonClicked, 5)
window.showAll
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.7.0" version = "0.7.1"
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,7 +1,7 @@
# This is the high level cairo module for Nim -- based on the low level ngtk3 module, manually tuned. # This is the high level cairo module for Nim -- based on the low level ngtk3 module, manually tuned.
# (c) S. Salewski 2017, cairo 1.15.6 # (c) S. Salewski 2017, cairo 1.15.6
# v0.7.0 # v0.7.1
# 27-JAN-2020 # 01-FEB-2020
# starting with gintro v.0.6.0 we split cairo into the gobject-introspection generated cairo.nim and this file. # starting with gintro v.0.6.0 we split cairo into the gobject-introspection generated cairo.nim and this file.
@ -136,6 +136,13 @@ type
var NUDK: ptr UserDataKey = cast[ptr UserDataKey](alloc(sizeof(UserDataKey))) var NUDK: ptr UserDataKey = cast[ptr UserDataKey](alloc(sizeof(UserDataKey)))
# copy from glib.nim
template fnew(a: untyped; finalizer: untyped) =
when compileOption("gc", "arc"):
new(a)
else:
new(a, finalizer)
proc gcuref(o: pointer) {.cdecl.} = proc gcuref(o: pointer) {.cdecl.} =
#echo "gcunref" #echo "gcunref"
GC_unref(cast[RootRef](o)) GC_unref(cast[RootRef](o))
@ -183,7 +190,7 @@ proc setUserData*(surface: Surface; key: ptr UserDataKey; userData: pointer; des
proc cairo_create*(target: ptr Surface00): ptr Context00 {.importc, libcairo.} proc cairo_create*(target: ptr Surface00): ptr Context00 {.importc, libcairo.}
# #
proc newContext*(target: Surface): Context = proc newContext*(target: Surface): Context =
new(result, gBoxedFreeCairoContext) fnew(result, gBoxedFreeCairoContext)
GC_ref(target) GC_ref(target)
result.impl = cairo_create(target.impl) result.impl = cairo_create(target.impl)
discard cairo_surface_set_user_data(target.impl, NUDK, cast[pointer](target), gcuref) discard cairo_surface_set_user_data(target.impl, NUDK, cast[pointer](target), gcuref)
@ -239,7 +246,7 @@ proc setUserData*(pattern: Pattern; key: ptr UserDataKey; userData: pointer; des
proc cairo_pop_group*(cr: ptr Context00): ptr Pattern00 {.importc, libcairo.} proc cairo_pop_group*(cr: ptr Context00): ptr Pattern00 {.importc, libcairo.}
# #
proc popGroup*(cr: Context): Pattern = proc popGroup*(cr: Context): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pop_group(cr.impl) result.impl = cairo_pop_group(cr.impl)
GC_Ref(result) GC_Ref(result)
discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -729,14 +736,14 @@ proc cairo_font_options_destroy*(options: ptr FontOptions00) {.importc, libcairo
proc cairo_font_options_create*(): ptr FontOptions00 {.importc, libcairo.} proc cairo_font_options_create*(): ptr FontOptions00 {.importc, libcairo.}
# #
proc newFontOptions*(): FontOptions = proc newFontOptions*(): FontOptions =
new(result, gBoxedFreeCairoFontOptions) fnew(result, gBoxedFreeCairoFontOptions)
result.impl = cairo_font_options_create() result.impl = cairo_font_options_create()
###discard cairo_font_options_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ###discard cairo_font_options_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_font_options_copy*(original: ptr FontOptions00): ptr FontOptions00 {.importc, libcairo.} proc cairo_font_options_copy*(original: ptr FontOptions00): ptr FontOptions00 {.importc, libcairo.}
# #
proc fontOptionsCopy*(original: FontOptions): FontOptions = proc fontOptionsCopy*(original: FontOptions): FontOptions =
new(result, gBoxedFreeCairoFontOptions) fnew(result, gBoxedFreeCairoFontOptions)
result.impl = cairo_font_options_copy(original.impl) result.impl = cairo_font_options_copy(original.impl)
proc cairo_font_options_status*(options: ptr FontOptions00): Status {.importc, libcairo.} proc cairo_font_options_status*(options: ptr FontOptions00): Status {.importc, libcairo.}
@ -849,7 +856,7 @@ proc cairo_get_font_options*(cr: ptr Context00; options: ptr FontOptions00) {.im
# #
proc getFontOptions*(cr: Context; options: var FontOptions) = proc getFontOptions*(cr: Context; options: var FontOptions) =
###new(options, gBoxedFreeCairoFontOptions) ###new(options, gBoxedFreeCairoFontOptions)
new(options, gBoxedFreeCairoFontOptions) fnew(options, gBoxedFreeCairoFontOptions)
options.impl = cairo_font_options_create() options.impl = cairo_font_options_create()
cairo_get_font_options(cr.impl, options.impl) cairo_get_font_options(cr.impl, options.impl)
@ -895,7 +902,7 @@ proc getFontFace*(cr: Context): FontFace =
let d = cairo_font_face_get_user_data(h, NUDK) let d = cairo_font_face_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
#assert false # may this happen? #assert false # may this happen?
new(result, fontFaceDestroy) fnew(result, fontFaceDestroy)
result.impl = h result.impl = h
# TODO check # TODO check
discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -947,7 +954,7 @@ proc getScaledFont*(cr: Context): ScaledFont =
let d = cairo_scaled_font_get_user_data(h, NUDK) let d = cairo_scaled_font_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
#assert false # may this happen? #assert false # may this happen?
new(result, gBoxedFreeCairoScaledFont) fnew(result, gBoxedFreeCairoScaledFont)
result.impl = h result.impl = h
discard cairo_scaled_font_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) discard cairo_scaled_font_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
discard cairo_scaled_font_reference(result.impl) discard cairo_scaled_font_reference(result.impl)
@ -1021,7 +1028,7 @@ proc cairo_scaled_font_create*(fontFace: ptr FontFace00;
fontMatrix: Matrix; ctm: Matrix; options: ptr FontOptions00): ptr ScaledFont00 {.importc, libcairo.} fontMatrix: Matrix; ctm: Matrix; options: ptr FontOptions00): ptr ScaledFont00 {.importc, libcairo.}
# #
proc scaledFontCreate*(fontFace: FontFace; fontMatrix: Matrix; ctm: Matrix; options: FontOptions): ScaledFont = proc scaledFontCreate*(fontFace: FontFace; fontMatrix: Matrix; ctm: Matrix; options: FontOptions): ScaledFont =
new(result, gBoxedFreeCairoScaledFont) fnew(result, gBoxedFreeCairoScaledFont)
GC_ref(fontFace) GC_ref(fontFace)
result.impl = cairo_scaled_font_create(fontFace.impl, fontMatrix, ctm, options.impl) result.impl = cairo_scaled_font_create(fontFace.impl, fontMatrix, ctm, options.impl)
discard cairo_scaled_font_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) discard cairo_scaled_font_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1079,7 +1086,7 @@ proc getFontFace*(scaledFont: ScaledFont): FontFace =
let d = cairo_font_face_get_user_data(h, NUDK) let d = cairo_font_face_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
assert false # may this happen? assert false # may this happen?
new(result, fontFaceDestroy) fnew(result, fontFaceDestroy)
result.impl = h result.impl = h
else: else:
result = cast[FontFace](d) result = cast[FontFace](d)
@ -1113,7 +1120,7 @@ proc cairo_scaled_font_get_font_options*(scaledFont: ptr ScaledFont00;
options: ptr FontOptions00) {.importc, libcairo.} options: ptr FontOptions00) {.importc, libcairo.}
# #
proc getFontOptions*(scaledFont: ScaledFont; options: var FontOptions) = proc getFontOptions*(scaledFont: ScaledFont; options: var FontOptions) =
new(options, gBoxedFreeCairoFontOptions) fnew(options, gBoxedFreeCairoFontOptions)
options.impl = cairo_font_options_create() options.impl = cairo_font_options_create()
cairo_scaled_font_get_font_options(scaledFont.impl, options.impl) cairo_scaled_font_get_font_options(scaledFont.impl, options.impl)
# #
@ -1123,7 +1130,7 @@ proc cairo_toy_font_face_create*(family: cstring; slant: FontSlant;
weight: FontWeight): ptr FontFace00 {.importc, libcairo.} weight: FontWeight): ptr FontFace00 {.importc, libcairo.}
# #
proc toyFontFaceCreate*(family: string; slant: FontSlant; weight: FontWeight): FontFace = proc toyFontFaceCreate*(family: string; slant: FontSlant; weight: FontWeight): FontFace =
new(result, fontFaceDestroy) fnew(result, fontFaceDestroy)
result.impl = cairo_toy_font_face_create(family, slant, weight) result.impl = cairo_toy_font_face_create(family, slant, weight)
### discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1146,7 +1153,7 @@ proc toyFontFaceGetWeight*(fontFace: FontFace): FontWeight =
proc cairo_user_font_face_create*(): ptr FontFace00 {.importc, libcairo.} proc cairo_user_font_face_create*(): ptr FontFace00 {.importc, libcairo.}
# #
proc userFontFaceCreate*(): FontFace = proc userFontFaceCreate*(): FontFace =
new(result, fontFaceDestroy) fnew(result, fontFaceDestroy)
result.impl = cairo_user_font_face_create() result.impl = cairo_user_font_face_create()
# there is no cairo_user_font_face_set_user_data() # there is no cairo_user_font_face_set_user_data()
# discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) # discard cairo_font_face_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1243,7 +1250,7 @@ proc getSource*(cr: Context): Pattern =
let h = cairo_get_source(cr.impl) let h = cairo_get_source(cr.impl)
let d = cairo_pattern_get_user_data(h, NUDK) let d = cairo_pattern_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_reference(h) result.impl = cairo_pattern_reference(h)
else: else:
result = cast[Pattern](d) result = cast[Pattern](d)
@ -1350,7 +1357,7 @@ proc getTarget*(cr: Context): Surface =
let d = cairo_surface_get_user_data(h, NUDK) let d = cairo_surface_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
assert false # may this happen? assert false # may this happen?
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = h result.impl = h
discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
discard cairo_surface_reference(result.impl) discard cairo_surface_reference(result.impl)
@ -1367,7 +1374,7 @@ proc getGroupTarget*(cr: Context): Surface =
let d = cairo_surface_get_user_data(h, NUDK) let d = cairo_surface_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
#assert false # may this happen? #assert false # may this happen?
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = h result.impl = h
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
### discard cairo_surface_reference(result.impl) ### discard cairo_surface_reference(result.impl)
@ -1385,14 +1392,14 @@ proc pathDestroy(path: Path) =
proc cairo_copy_path*(cr: ptr Context00): ptr Path00 {.importc, libcairo.} proc cairo_copy_path*(cr: ptr Context00): ptr Path00 {.importc, libcairo.}
# #
proc copyPath*(cr: Context): Path = proc copyPath*(cr: Context): Path =
new(result, pathDestroy) fnew(result, pathDestroy)
result.impl = cairo_copy_path(cr.impl) result.impl = cairo_copy_path(cr.impl)
#discard cairo_path_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) #discard cairo_path_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_copy_path_flat*(cr: ptr Context00): ptr Path00 {.importc, libcairo.} proc cairo_copy_path_flat*(cr: ptr Context00): ptr Path00 {.importc, libcairo.}
# #
proc copyPathFlat*(cr: Context): Path = proc copyPathFlat*(cr: Context): Path =
new(result, pathDestroy) fnew(result, pathDestroy)
result.impl = cairo_copy_path_flat(cr.impl) result.impl = cairo_copy_path_flat(cr.impl)
proc cairo_append_path*(cr: ptr Context00; path: ptr Path00) {.importc, libcairo.} proc cairo_append_path*(cr: ptr Context00; path: ptr Path00) {.importc, libcairo.}
@ -1474,7 +1481,7 @@ proc cairo_surface_create_similar*(other: ptr Surface00; content: Content; width
ptr Surface00 {.importc, libcairo.} ptr Surface00 {.importc, libcairo.}
proc createSimilar*(other: Surface; content: Content; width, height: int): Surface = proc createSimilar*(other: Surface; content: Content; width, height: int): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_surface_create_similar(other.impl, content, width.cint, height.cint) result.impl = cairo_surface_create_similar(other.impl, content, width.cint, height.cint)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1482,7 +1489,7 @@ proc cairo_surface_create_similar_image*(other: ptr Surface00; format: Format; w
ptr Surface00 {.importc, libcairo.} ptr Surface00 {.importc, libcairo.}
# #
proc createSimilarImage*(other: Surface; format: Format; width, height: int): Surface = proc createSimilarImage*(other: Surface; format: Format; width, height: int): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_surface_create_similar_image(other.impl, format, width.cint, height.cint) result.impl = cairo_surface_create_similar_image(other.impl, format, width.cint, height.cint)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1495,14 +1502,14 @@ proc cairo_surface_map_to_image*(surface: ptr Surface00; extents: RectangleInt):
# #
proc mapToImage*(surface: Surface; extents: RectangleInt): Surface = proc mapToImage*(surface: Surface; extents: RectangleInt): Surface =
#new(result, destroy) # no idea currently #new(result, destroy) # no idea currently
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_surface_map_to_image(surface.impl, extents) result.impl = cairo_surface_map_to_image(surface.impl, extents)
proc cairo_surface_create_for_rectangle*(target: ptr Surface00; x, y, width, height: cdouble): proc cairo_surface_create_for_rectangle*(target: ptr Surface00; x, y, width, height: cdouble):
ptr Surface00 {.importc, libcairo.} ptr Surface00 {.importc, libcairo.}
# #
proc surfaceCreateForRectangle*(target: Surface; x, y, width, height: float): Surface = proc surfaceCreateForRectangle*(target: Surface; x, y, width, height: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_surface_create_for_rectangle(target.impl, x.cdouble, y.cdouble, width.cdouble, height.cdouble) result.impl = cairo_surface_create_for_rectangle(target.impl, x.cdouble, y.cdouble, width.cdouble, height.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1515,7 +1522,7 @@ proc cairo_surface_create_observer*(target: ptr Surface00;
mode: SurfaceObserverMode): ptr Surface00 {.importc, libcairo.} mode: SurfaceObserverMode): ptr Surface00 {.importc, libcairo.}
# #
proc createObserver*(target: Surface; mode: SurfaceObserverMode): Surface = proc createObserver*(target: Surface; mode: SurfaceObserverMode): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_surface_create_observer(target.impl, mode) result.impl = cairo_surface_create_observer(target.impl, mode)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1563,7 +1570,7 @@ proc getDevice*(surface: Surface): Device =
let d = cairo_device_get_user_data(h, NUDK) let d = cairo_device_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
assert false # may this happen? assert false # may this happen?
new(result, deviceDestroy) fnew(result, deviceDestroy)
result.impl = h result.impl = h
discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
discard cairo_device_reference(result.impl) discard cairo_device_reference(result.impl)
@ -1639,7 +1646,7 @@ proc supportsMimeType*(surface: Surface; mimeType: string): bool =
proc cairo_surface_get_font_options*(surface: ptr Surface00; options: ptr FontOptions00) {.importc, libcairo.} proc cairo_surface_get_font_options*(surface: ptr Surface00; options: ptr FontOptions00) {.importc, libcairo.}
proc getFontOptions*(surface: Surface; options: var FontOptions) = proc getFontOptions*(surface: Surface; options: var FontOptions) =
new(options, gBoxedFreeCairoFontOptions) fnew(options, gBoxedFreeCairoFontOptions)
options.impl = cairo_font_options_create() options.impl = cairo_font_options_create()
cairo_surface_get_font_options(surface.impl, options.impl) cairo_surface_get_font_options(surface.impl, options.impl)
@ -1716,7 +1723,7 @@ proc hasShowTextGlyphs*(surface: Surface): bool =
proc cairo_image_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.} proc cairo_image_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.}
# #
proc imageSurfaceCreate*(format: Format; width, height: int): Surface = proc imageSurfaceCreate*(format: Format; width, height: int): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_image_surface_create(format, width.cint, height.cint) result.impl = cairo_image_surface_create(format, width.cint, height.cint)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1755,7 +1762,7 @@ when CAIRO_HAS_PNG_FUNCTIONS:
proc cairo_image_surface_create_from_png*(filename: cstring): ptr Surface00 {.importc, libcairo.} proc cairo_image_surface_create_from_png*(filename: cstring): ptr Surface00 {.importc, libcairo.}
proc imageSurfaceCreateFromPng*(filename: string): Surface = proc imageSurfaceCreateFromPng*(filename: string): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_image_surface_create_from_png(filename) result.impl = cairo_image_surface_create_from_png(filename)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1763,14 +1770,14 @@ when CAIRO_HAS_PNG_FUNCTIONS:
closure: pointer): ptr Surface00 {.importc, libcairo.} closure: pointer): ptr Surface00 {.importc, libcairo.}
# #
proc imageSurfaceCreateFromPngStream*(readFunc: ReadFunc00; closure: pointer): Surface = proc imageSurfaceCreateFromPngStream*(readFunc: ReadFunc00; closure: pointer): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_image_surface_create_from_png_stream(readFunc, closure) result.impl = cairo_image_surface_create_from_png_stream(readFunc, closure)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_recording_surface_create*(content: Content; extents: Rectangle): ptr Surface00 {.importc, libcairo.} proc cairo_recording_surface_create*(content: Content; extents: Rectangle): ptr Surface00 {.importc, libcairo.}
# #
proc recordingSurfaceCreate*(content: Content; extents: Rectangle): Surface = proc recordingSurfaceCreate*(content: Content; extents: Rectangle): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_recording_surface_create(content, extents) result.impl = cairo_recording_surface_create(content, extents)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1816,7 +1823,7 @@ proc cairo_pattern_create_raster_source*(userData: pointer; content: Content; wi
ptr Pattern00 {.importc, libcairo.} ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateRasterSource*(userData: pointer; content: Content; width, height: int): Pattern = proc patternCreateRasterSource*(userData: pointer; content: Content; width, height: int): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_raster_source(userData, content, width.cint, height.cint) result.impl = cairo_pattern_create_raster_source(userData, content, width.cint, height.cint)
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -1875,42 +1882,42 @@ proc rasterSourcePatternGetFinish*(pattern: Pattern): RasterSourceFinishFunc00 =
proc cairo_pattern_create_rgb*(red, green, blue: cdouble): ptr Pattern00 {.importc, libcairo.} proc cairo_pattern_create_rgb*(red, green, blue: cdouble): ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateRgb*(red, green, blue: float): Pattern = proc patternCreateRgb*(red, green, blue: float): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_rgb(red.cdouble, green.cdouble, blue.cdouble) result.impl = cairo_pattern_create_rgb(red.cdouble, green.cdouble, blue.cdouble)
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_pattern_create_rgba*(red, green, blue, alpha: cdouble): ptr Pattern00 {.importc, libcairo.} proc cairo_pattern_create_rgba*(red, green, blue, alpha: cdouble): ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateRgba*(red, green, blue, alpha: float): Pattern = proc patternCreateRgba*(red, green, blue, alpha: float): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_rgba(red.cdouble, green.cdouble, blue.cdouble, alpha.cdouble) result.impl = cairo_pattern_create_rgba(red.cdouble, green.cdouble, blue.cdouble, alpha.cdouble)
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_pattern_create_for_surface*(surface: ptr Surface00): ptr Pattern00 {.importc, libcairo.} proc cairo_pattern_create_for_surface*(surface: ptr Surface00): ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateForSurface*(surface: Surface): Pattern = proc patternCreateForSurface*(surface: Surface): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_for_surface(surface.impl) result.impl = cairo_pattern_create_for_surface(surface.impl)
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_pattern_create_linear*(x0, y0, x1, y1: cdouble): ptr Pattern00 {.importc, libcairo.} proc cairo_pattern_create_linear*(x0, y0, x1, y1: cdouble): ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateLinear*(x0, y0, x1, y1: float): Pattern = proc patternCreateLinear*(x0, y0, x1, y1: float): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_linear(x0.cdouble, y0.cdouble, x1.cdouble, y1.cdouble) result.impl = cairo_pattern_create_linear(x0.cdouble, y0.cdouble, x1.cdouble, y1.cdouble)
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: cdouble): ptr Pattern00 {.importc, libcairo.} proc cairo_pattern_create_radial*(cx0, cy0, radius0, cx1, cy1, radius1: cdouble): ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateRadial*(cx0, cy0, radius0, cx1, cy1, radius1: float): Pattern = proc patternCreateRadial*(cx0, cy0, radius0, cx1, cy1, radius1: float): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_radial(cx0.cdouble, cy0.cdouble, radius0.cdouble, cx1.cdouble, cy1.cdouble, radius1.cdouble) result.impl = cairo_pattern_create_radial(cx0.cdouble, cy0.cdouble, radius0.cdouble, cx1.cdouble, cy1.cdouble, radius1.cdouble)
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_pattern_create_mesh*(): ptr Pattern00 {.importc, libcairo.} proc cairo_pattern_create_mesh*(): ptr Pattern00 {.importc, libcairo.}
# #
proc patternCreateMesh*(): Pattern = proc patternCreateMesh*(): Pattern =
new(result, gBoxedFreeCairoPattern) fnew(result, gBoxedFreeCairoPattern)
result.impl = cairo_pattern_create_mesh() result.impl = cairo_pattern_create_mesh()
### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_pattern_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2030,7 +2037,7 @@ proc getSurface*(pattern: Pattern; surface: var Surface): Status =
let d = cairo_surface_get_user_data(h, NUDK) let d = cairo_surface_get_user_data(h, NUDK)
if d.isNil: if d.isNil:
assert false # may this happen? assert false # may this happen?
new(surface, gBoxedFreeCairoSurface) fnew(surface, gBoxedFreeCairoSurface)
surface.impl = h surface.impl = h
discard cairo_surface_set_user_data(surface.impl, NUDK, cast[pointer](surface), gcuref) discard cairo_surface_set_user_data(surface.impl, NUDK, cast[pointer](surface), gcuref)
discard cairo_surface_reference(surface.impl) discard cairo_surface_reference(surface.impl)
@ -2090,7 +2097,7 @@ proc meshPatternGetPatchCount*(pattern: Pattern; count: var int): Status =
proc cairo_mesh_pattern_get_path*(pattern: ptr Pattern00; patchNum: cuint): ptr Path00 {.importc, libcairo.} proc cairo_mesh_pattern_get_path*(pattern: ptr Pattern00; patchNum: cuint): ptr Path00 {.importc, libcairo.}
# #
proc meshPatternGetPath*(pattern: Pattern; patchNum: int): Path = proc meshPatternGetPath*(pattern: Pattern; patchNum: int): Path =
new(result, pathDestroy) fnew(result, pathDestroy)
result.impl = cairo_mesh_pattern_get_path(pattern.impl, patchNum.cuint) result.impl = cairo_mesh_pattern_get_path(pattern.impl, patchNum.cuint)
proc cairo_mesh_pattern_get_corner_color_rgba*(pattern: ptr Pattern00; patchNum, cornerNum: cuint; proc cairo_mesh_pattern_get_corner_color_rgba*(pattern: ptr Pattern00; patchNum, cornerNum: cuint;
@ -2182,14 +2189,14 @@ proc destroy*(region: Region) =
proc cairo_region_create*(): ptr Region00 {.importc, libcairo.} proc cairo_region_create*(): ptr Region00 {.importc, libcairo.}
# #
proc regionCreate*(): Region = proc regionCreate*(): Region =
new(result, gBoxedFreeCairoRegion) fnew(result, gBoxedFreeCairoRegion)
result.impl = cairo_region_create() result.impl = cairo_region_create()
### discard cairo_region_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_region_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_region_create_rectangle*(rectangle: RectangleInt): ptr Region00 {.importc, libcairo.} proc cairo_region_create_rectangle*(rectangle: RectangleInt): ptr Region00 {.importc, libcairo.}
# #
proc regionCreateRectangle*(rectangle: RectangleInt): Region = proc regionCreateRectangle*(rectangle: RectangleInt): Region =
new(result, gBoxedFreeCairoRegion) fnew(result, gBoxedFreeCairoRegion)
result.impl = cairo_region_create_rectangle(rectangle) result.impl = cairo_region_create_rectangle(rectangle)
# TODO # TODO
@ -2199,7 +2206,7 @@ proc cairo_region_create_rectangles*(rects: RectangleInt; count: cint): ptr Regi
proc cairo_region_copy*(original: ptr Region00): ptr Region00 {.importc, libcairo.} proc cairo_region_copy*(original: ptr Region00): ptr Region00 {.importc, libcairo.}
# #
proc regionCopy*(original: Region): Region = proc regionCopy*(original: Region): Region =
new(result, gBoxedFreeCairoRegion) fnew(result, gBoxedFreeCairoRegion)
result.impl = cairo_region_copy(original.impl) result.impl = cairo_region_copy(original.impl)
proc cairo_region_reference*(region: ptr Region00): ptr Region00 {.importc, libcairo.} proc cairo_region_reference*(region: ptr Region00): ptr Region00 {.importc, libcairo.}
@ -2307,7 +2314,7 @@ when CAIRO_HAS_PDF_SURFACE:
importc, libcairo.} importc, libcairo.}
proc pdfSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface = proc pdfSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_pdf_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble) result.impl = cairo_pdf_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2315,7 +2322,7 @@ when CAIRO_HAS_PDF_SURFACE:
closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.} closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
# #
proc pdfSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface = proc pdfSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_pdf_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble) result.impl = cairo_pdf_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2388,7 +2395,7 @@ when CAIRO_HAS_PS_SURFACE:
importc, libcairo.} importc, libcairo.}
# #
proc psSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface = proc psSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_ps_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble) result.impl = cairo_ps_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2396,7 +2403,7 @@ when CAIRO_HAS_PS_SURFACE:
widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.} widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
# #
proc psSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface = proc psSurfaceCreateForStream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_ps_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble) result.impl = cairo_ps_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2455,7 +2462,7 @@ when CAIRO_HAS_SVG_SURFACE:
importc, libcairo.} importc, libcairo.}
# #
proc svgSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface = proc svgSurfaceCreate*(filename: string; widthInPoints, heightInPoints: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_svg_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble) result.impl = cairo_svg_surface_create(filename, widthInPoints.cdouble, heightInPoints.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2463,7 +2470,7 @@ when CAIRO_HAS_SVG_SURFACE:
closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.} closure: pointer; widthInPoints, heightInPoints: cdouble): ptr Surface00 {.importc, libcairo.}
# #
proc svgSurfaceCreateForstream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface = proc svgSurfaceCreateForstream*(writeFunc: WriteFunc00; closure: pointer; widthInPoints, heightInPoints: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_svg_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble) result.impl = cairo_svg_surface_create_for_stream(writeFunc, closure, widthInPoints.cdouble, heightInPoints.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2487,14 +2494,14 @@ when CAIRO_HAS_XML_SURFACE:
proc cairo_xml_create*(filename: cstring): ptr Device00 {.importc, libcairo.} proc cairo_xml_create*(filename: cstring): ptr Device00 {.importc, libcairo.}
# #
proc xml_create*(filename: string): Device = proc xml_create*(filename: string): Device =
new(result, deviceDestroy) fnew(result, deviceDestroy)
result.impl = cairo_xml_create(filename) result.impl = cairo_xml_create(filename)
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_xml_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.} proc cairo_xml_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.}
# #
proc xmlCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device = proc xmlCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device =
new(result, deviceDestroy) fnew(result, deviceDestroy)
result.impl = cairo_xml_create_for_stream(writeFunc, closure) result.impl = cairo_xml_create_for_stream(writeFunc, closure)
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2502,7 +2509,7 @@ when CAIRO_HAS_XML_SURFACE:
importc, libcairo.} importc, libcairo.}
# #
proc xmlSurfaceCreate*(xml: Device; content: Content; width, height: float): Surface = proc xmlSurfaceCreate*(xml: Device; content: Content; width, height: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_xml_surface_create(xml.impl, content, width.cdouble, height.cdouble) result.impl = cairo_xml_surface_create(xml.impl, content, width.cdouble, height.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2519,14 +2526,14 @@ when CAIRO_HAS_SCRIPT_SURFACE:
proc cairo_script_create*(filename: cstring): ptr Device00 {.importc, libcairo.} proc cairo_script_create*(filename: cstring): ptr Device00 {.importc, libcairo.}
# #
proc scriptCreate*(filename: string): Device = proc scriptCreate*(filename: string): Device =
new(result, deviceDestroy) fnew(result, deviceDestroy)
result.impl = cairo_script_create(filename) result.impl = cairo_script_create(filename)
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
proc cairo_script_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.} proc cairo_script_create_for_stream*(writeFunc: WriteFunc00; closure: pointer): ptr Device00 {.importc, libcairo.}
# #
proc scriptCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device = proc scriptCreateForStream*(writeFunc: WriteFunc00; closure: pointer): Device =
new(result, deviceDestroy) fnew(result, deviceDestroy)
result.impl = cairo_script_create_for_stream(writeFunc, closure) result.impl = cairo_script_create_for_stream(writeFunc, closure)
### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_device_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2549,7 +2556,7 @@ when CAIRO_HAS_SCRIPT_SURFACE:
importc, libcairo.} importc, libcairo.}
# #
proc scriptSurfaceCreate*(script: Device; content: Content; width, height: float): Surface = proc scriptSurfaceCreate*(script: Device; content: Content; width, height: float): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_script_surface_create(script.impl, content, width.cdouble, height.cdouble) result.impl = cairo_script_surface_create(script.impl, content, width.cdouble, height.cdouble)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2557,7 +2564,7 @@ when CAIRO_HAS_SCRIPT_SURFACE:
target: ptr Surface00): ptr Surface00 {.importc, libcairo.} target: ptr Surface00): ptr Surface00 {.importc, libcairo.}
# #
proc scriptSurfaceCreateForTarget*(script: Device; target: Surface): Surface = proc scriptSurfaceCreateForTarget*(script: Device; target: Surface): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_script_surface_create_for_target(script.impl, target.impl) result.impl = cairo_script_surface_create_for_target(script.impl, target.impl)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2571,7 +2578,7 @@ when CAIRO_HAS_SKIA_SURFACE:
proc cairo_skia_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.} proc cairo_skia_surface_create*(format: Format; width, height: cint): ptr Surface00 {.importc, libcairo.}
# #
proc skiaSurfaceCreate*(format: Format; width, height: int): Surface = proc skiaSurfaceCreate*(format: Format; width, height: int): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_skia_surface_create(format, width.cint, height.cint) result.impl = cairo_skia_surface_create(format, width.cint, height.cint)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2613,7 +2620,7 @@ when CAIRO_HAS_TEE_SURFACE:
proc cairo_tee_surface_create*(master: ptr Surface00): ptr Surface00 {.importc, libcairo.} proc cairo_tee_surface_create*(master: ptr Surface00): ptr Surface00 {.importc, libcairo.}
# #
proc teeSurfaceCreate*(master: Surface): Surface = proc teeSurfaceCreate*(master: Surface): Surface =
new(result, gBoxedFreeCairoSurface) fnew(result, gBoxedFreeCairoSurface)
result.impl = cairo_tee_surface_create(master.impl) result.impl = cairo_tee_surface_create(master.impl)
### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref) ### discard cairo_surface_set_user_data(result.impl, NUDK, cast[pointer](result), gcuref)
@ -2633,5 +2640,5 @@ when CAIRO_HAS_TEE_SURFACE:
discard cairo_tee_surface_index(surface.impl, index.cuint) discard cairo_tee_surface_index(surface.impl, index.cuint)
return surface return surface
# 2636 lines # 2636 lines new(

View file

@ -1,4 +1,4 @@
# # https://forum.nim-lang.org/t/5937
# #
# Nimrod Combinatorics Module # Nimrod Combinatorics Module
# (c) Copyright 2014 Reimer Behrends # (c) Copyright 2014 Reimer Behrends
@ -167,15 +167,22 @@ when isMainModule:
i i
proc mcoeff(a, b: int): int = proc mcoeff(a, b: int): int =
binom(a+b-1, b) binom(a+b-1, b)
doAssert count(permutations[int]([])) == 1
doAssert count(permutations([1,2,3,4,5])) == fac(5) for x in combinations([1,2,3], 2):
doAssert count(permutations(["a", "b", "c"])) == fac(3) echo x
doAssert count(combinations([1,2,3,4], 1)) == binom(4, 1)
doAssert count(combinations([1,2,3,4], 2)) == binom(4, 2)
doAssert count(combinations([1,2,3,4], 3)) == binom(4, 3) #doAssert count(permutations[int]([])) == 1
doAssert count(combinations(["a", "b", "c", "d", "e"], 3)) == 10 assert toSeq(permutations([1,2,3,4,5])).len == fac(5)
doAssert count(multicombinations([1,2,3,4], 1)) == mcoeff(4, 1) assert toSeq(permutations([1,2,3,4,5])).len == fac(5)
doAssert count(multicombinations([1,2,3,4], 2)) == mcoeff(4, 2) assert toSeq(permutations(["a", "b", "c"])).len == fac(3)
doAssert count(multicombinations([1,2,3,4], 3)) == mcoeff(4, 3) assert toSeq(combinations([1,2,3,4], 1)).len == binom(4, 1)
doAssert count(tuples([1,2,3,4], 3)) == 4*4*4 assert toSeq(combinations([1,2,3,4], 2)).len == binom(4, 2)
doAssert count(tuples([1,2], 10)) == 1024 assert toSeq(combinations([1,2,3,4], 3)).len == binom(4, 3)
assert toSeq(combinations(["a", "b", "c", "d", "e"], 3)).len == 10
assert toSeq(multicombinations([1,2,3,4], 1)).len == mcoeff(4, 1)
assert toSeq(multicombinations([1,2,3,4], 2)).len == mcoeff(4, 2)
assert toSeq(multicombinations([1,2,3,4], 3)).len == mcoeff(4, 3)
assert toSeq(tuples([1,2,3,4], 3)).len == 4*4*4
assert toSeq(tuples([1,2], 10)).len == 1024

View file

@ -1,11 +1,12 @@
# 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.7.0 2020-JAN-27 # v 0.7.1 2020-FEB-20
# (c) S. Salewski 2018 # (c) S. Salewski 2018
# https://wiki.gnome.org/Projects/GObjectIntrospection # https://wiki.gnome.org/Projects/GObjectIntrospection
# https://developer.gnome.org/gi/stable/ # https://developer.gnome.org/gi/stable/
# https://mail.gnome.org/archives/gtk-devel-list/2005-April/msg00095.html # https://mail.gnome.org/archives/gtk-devel-list/2005-April/msg00095.html
# https://ptomato.wordpress.com/2018/11/06/taking-out-the-garbage/
# /usr/share/gir-1.0/GLib-2.0.gir # /usr/share/gir-1.0/GLib-2.0.gir
# you may also compare the currently unmaintained work of # you may also compare the currently unmaintained work of
@ -15,7 +16,7 @@
# https://github.com/StefanSalewski/oldgtk3 # https://github.com/StefanSalewski/oldgtk3
# as those were created with c2nim and work for 32/64 bit and linux, windows and macos # as those were created with c2nim and work for 32/64 bit and linux, windows and macos
# Currently we intentionally do not free any resources! # Currently we intentionally do not free any resources in this generator script!
# First goal was creating low level bindings similar to current oldgtk3. #XXX DONE # First goal was creating low level bindings similar to current oldgtk3. #XXX DONE
# Then we added the high level wrapper similar as done in Nim's libui wrapper. #XXX Mostly DONE # Then we added the high level wrapper similar as done in Nim's libui wrapper. #XXX Mostly DONE
@ -27,10 +28,15 @@
# - ParamSpec is reported as object, but has no parent # not really a bug, gst has more gobjects without parent # - ParamSpec is reported as object, but has no parent # not really a bug, gst has more gobjects without parent
# - gBaseInfoGetName() is "" for g_iconv() #XXX fixed # - gBaseInfoGetName() is "" for g_iconv() #XXX fixed
# - dirSep is wrong for unix -- that is an already reported gi bug # - dirSep is wrong for unix -- that is an already reported gi bug
# missing nullable flag for some functions, see https://discourse.gnome.org/t/missing-nullable-tag-as-in-gtk-css-section-get-file/2814
# - well there are more than 140 open issues about gobject introspection in gnome bugzilla :-( # - well there are more than 140 open issues about gobject introspection in gnome bugzilla :-(
# This module is really ugly currently -- the first goal was to get a working gi solution # This module is really ugly currently -- the first goal was to get a working gi solution
# NOTE: Currently we support subclassing only for constructor functions like gtk_button_new() -- for
# these we provide an initButton() additional to the well know newButton(). Maybe other functions
# with a result variable that we may intent to subclass should get a init() variant also...
from os import `/`, paramCount from os import `/`, paramCount
import gir, gobject, glib import gir, gobject, glib
import strutils import strutils
@ -143,7 +149,7 @@ proc mysnakeToCamel(s: cstring): string =
result = "QQQ" result = "QQQ"
#assert(false) #assert(false)
proc renumber(s: var string; i: int) = proc renumber(s: var string; i: int) = # only in use when WriteFields
if s[^1].isDigit: if s[^1].isDigit:
s.insert($i, s.high) s.insert($i, s.high)
else: else:
@ -435,7 +441,7 @@ proc modPrefix(t: GITypeInfo; sym: string; full = true): string =
if tag == GITypeTag.INTERFACE: if tag == GITypeTag.INTERFACE:
let iface = gTypeInfoGetInterface(t) let iface = gTypeInfoGetInterface(t)
if gBaseInfoGetType(iface) == GIInfoType.CALLBACK: if gBaseInfoGetType(iface) == GIInfoType.CALLBACK:
discard assert false # discard
else: else:
var ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii var ns = ($gBaseInfoGetNamespace(iface)).toLowerAscii
if ns != moduleNamespace: if ns != moduleNamespace:
@ -667,6 +673,7 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (
arrLex = " let $1 = $2($3.len)\n" % [resus[resusLen][0], h, lastName] arrLex = " let $1 = $2($3.len)\n" % [resus[resusLen][0], h, lastName]
resus.delete(resusLen) resus.delete(resusLen)
else: else:
assert false
arrLex = "" #"#??\n" arrLex = "" #"#??\n"
resul = makeResul(resus, self, resusres).isplit(sym.len + "proc".len) resul = makeResul(resus, self, resusres).isplit(sym.len + "proc".len)
return (resul, arglist, replist, arrLex, blex) return (resul, arglist, replist, arrLex, blex)
@ -693,20 +700,22 @@ proc genPars(info: GICallableInfo; genProxy = false; binfo: GIBaseInfo = nil): (
proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) = proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
template gobjectTemp(ignoreFinalizer: bool): untyped = template gobjectTemp(): untyped =
assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.NOTHING, EVERYTHING}) # both occur assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.NOTHING, EVERYTHING}) # both occur
methodBuffer.writeLine(" let gobj = " & sym & arglist) methodBuffer.writeLine(" let gobj = " & sym & arglist)
methodBuffer.writeLine(" if g_object_get_qdata(gobj, Quark) != nil:") if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" result = cast[type(result)](g_object_get_qdata(gobj, Quark))") methodBuffer.writeLine(" if gobj.isNil:")
methodBuffer.writeLine(" return nil") # https://github.com/StefanSalewski/gintro/issues/63
methodBuffer.writeLine(" let qdata = g_object_get_qdata(gobj, Quark)")
methodBuffer.writeLine(" if qdata != nil:")
methodBuffer.writeLine(" result = cast[type(result)](qdata)")
methodBuffer.writeLine(" assert(result.impl == gobj)") methodBuffer.writeLine(" assert(result.impl == gobj)")
methodBuffer.writeLine(" else:") methodBuffer.writeLine(" else:")
if sym == "g_object_ref" or sym == "g_object_ref_sink": if sym == "g_object_ref" or sym == "g_object_ref_sink":
methodBuffer.writeLine(" assert(false)") methodBuffer.writeLine(" assert(false)")
assert false
else: else:
if ignoreFinalizer: # with ARC we have no finalizer support for user defined subclasses, so we have to leak mem! methodBuffer.writeLine(" fnew(result, $1finalizeGObject)" % [mprefix])
methodBuffer.writeLine(" new(result)")
else:
methodBuffer.writeLine(" new(result, $1finalizeGObject)" % [mprefix])
methodBuffer.writeLine(" result.impl = gobj") methodBuffer.writeLine(" result.impl = gobj")
methodBuffer.writeLine(" GC_ref(result)") methodBuffer.writeLine(" GC_ref(result)")
methodBuffer.writeLine(" discard g_object_ref_sink(result.impl)") methodBuffer.writeLine(" discard g_object_ref_sink(result.impl)")
@ -719,6 +728,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
template findFreeProc(info: GIBaseInfo; noWarning: bool): untyped = template findFreeProc(info: GIBaseInfo; noWarning: bool): untyped =
if gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT: if gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT:
if gBaseInfoGetType(info) == GIInfoType.UNION: if gBaseInfoGetType(info) == GIInfoType.UNION:
# assert false executed for gtk3
freeMe = gUnionInfoFindMethod(info, "free") freeMe = gUnionInfoFindMethod(info, "free")
if freeMe.isNil: if freeMe.isNil:
freeMe = gUnionInfoFindMethod(info, "unref") freeMe = gUnionInfoFindMethod(info, "unref")
@ -729,6 +739,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
freeMe = gStructInfoFindMethod(info, "unref") freeMe = gStructInfoFindMethod(info, "unref")
if freeMe == nil: if freeMe == nil:
if fixedDestroyNames.contains(sym): if fixedDestroyNames.contains(sym):
assert false
freeMeName = fixedDestroyNames[sym] freeMeName = fixedDestroyNames[sym]
else: else:
assert (not fixedDestroyNames.contains(sym)) assert (not fixedDestroyNames.contains(sym))
@ -803,6 +814,7 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
if sym == "gtk_selection_data_get_targets": return if sym == "gtk_selection_data_get_targets": return
if sym == "g_strfreev": return if sym == "g_strfreev": return
if sym == "g_signal_emitv": return if sym == "g_signal_emitv": return
if sym == "g_object_ref": return # supress Hint: 'g_object_ref' is declared but not used
try: try:
(plist, arglist, replist, arrLex) = genPars(mInfo, false, info) (plist, arglist, replist, arrLex) = genPars(mInfo, false, info)
@ -907,7 +919,10 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
if isGObject: if isGObject:
# CAUTION: some procs are advertised as constructor but do not construct new objects, # CAUTION: some procs are advertised as constructor but do not construct new objects,
# they just return existing ones as gdk_cursor_new_from_name() # they just return existing ones as gdk_cursor_new_from_name()
gobjectTemp(i > 0) 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: elif gCallableInfoGetCallerOwns(minfo) == GITransfer.CONTAINER:
assert false assert false
elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or #: ################### elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or #: ###################
@ -925,27 +940,38 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
#if sym == "g_closure_new_simple" or sym == "g_closure_new_object": #if sym == "g_closure_new_simple" or sym == "g_closure_new_object":
# freeMeName = "unref" # TODO GI bug? # freeMeName = "unref" # TODO GI bug?
#assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING}) #assert(gCallableInfoGetCallerOwns(minfo) in {GITransfer.EVERYTHING, GITransfer.NOTHING})
if i > 0: # with ARC we have no finalizer support for user defined subclasses, so we have to leak mem! 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)") methodBuffer.writeLine(" new(result)")
elif boxedFreeMeName != "": elif boxedFreeMeName != "":
methodBuffer.writeLine(" new(result, $1)" % boxedFreeMeName) methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName)
elif freeMeName == "": elif freeMeName == "":
assert false
methodBuffer.writeLine(" new(result)") methodBuffer.writeLine(" new(result)")
else: else:
methodBuffer.writeLine(" new(result, $1)" % freeMeName) methodBuffer.writeLine(" fnew(result, $1)" % freeMeName)
methodBuffer.writeLine(" result.impl = " & sym & arglist) methodBuffer.writeLine(" result.impl = " & sym & arglist)
#if gBaseInfoGetName(info) == "Variant": #if gBaseInfoGetName(info) == "Variant":
# methodBuffer.writeLine(" discard g_variant_ref_sink(result.impl)") # methodBuffer.writeLine(" discard g_variant_ref_sink(result.impl)")
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"):
methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if result.impl.isNil:")
methodBuffer.writeLine(" return nil")
else: else:
echo "skipped ", sym echo "skipped ", sym
#assert false assert false
#assert gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING #assert gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING
#methodBuffer.writeLine(" new(result)") #methodBuffer.writeLine(" new(result)")
#methodBuffer.writeLine(" result.ignoreFinalizer = true") #methodBuffer.writeLine(" result.ignoreFinalizer = true")
#methodBuffer.writeLine(" result.impl = " & sym & arglist) #methodBuffer.writeLine(" result.impl = " & sym & arglist)
if i == 0 and gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: #if (gFunctionInfoGetFlags(mInfo).int and GIFunctionInfoFlags.IS_CONSTRUCTOR.int) == 0 and
methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC. # gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING:
# methodBuffer.writeLine(" result.ignoreFinalizer = true") # as we have always to attach one with ARC.
for k, v in replist: for k, v in replist:
assert false
methodBuffer.writeLine(" $1 = $2($3_00)" % [k, ct3nt(v), k.strip(chars = {'`'})]) methodBuffer.writeLine(" $1 = $2($3_00)" % [k, ct3nt(v), k.strip(chars = {'`'})])
elif isProxyCandidate(ret2): # BLOCKMARK8 elif isProxyCandidate(ret2): # BLOCKMARK8
assert (gCallableInfoGetCallerOwns(minfo) in {GITransfer.NOTHING, GITransfer.EVERYTHING}) # both occur assert (gCallableInfoGetCallerOwns(minfo) in {GITransfer.NOTHING, GITransfer.EVERYTHING}) # both occur
@ -958,19 +984,20 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
for k, v in replist: for k, v in replist:
methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v, k]) methodBuffer.writeLine(" var $1_00 = $2($3)" % [k.strip(chars = {'`'}), v, k])
if isGObject: if isGObject:
gobjectTemp(false) gobjectTemp()
elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or elif gCallableInfoGetCallerOwns(minfo) == GITransfer.EVERYTHING or
gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for ARC we have always to use the same finalizer! gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: # for ARC we have always to use the same finalizer!
let tag = gTypeInfoGetTag(ret2) let tag = gTypeInfoGetTag(ret2)
assert tag == GITypeTag.INTERFACE assert tag == GITypeTag.INTERFACE
var iface = gTypeInfoGetInterface(ret2) var iface = gTypeInfoGetInterface(ret2)
if gBaseInfoGetType(iface) == GIInfoType.INTERFACE: if gBaseInfoGetType(iface) == GIInfoType.INTERFACE:
iface = gInterfaceInfoGetIfaceStruct(iface) gobjectTemp()
methodBuffer.writeLine(" new(result, $1genericGObjectUnref)" % [mprefix]) #iface = gInterfaceInfoGetIfaceStruct(iface)
methodBuffer.writeLine(" result.impl = " & sym & arglist) #methodBuffer.writeLine(" fnew(result, $1genericGObjectUnref) # Interface" % [mprefix])
elif gBaseInfoGetType(iface) == GIInfoType.OBJECT: #methodBuffer.writeLine(" result.impl = " & sym & arglist)
elif gBaseInfoGetType(iface) == GIInfoType.OBJECT: # rare, ParamSpec in gobject.nim
#echo "XXXXXXXXXXXXXXXXX what shall we do? for ", sym #echo "XXXXXXXXXXXXXXXXX what shall we do? for ", sym
methodBuffer.writeLine(" new(result, $1genericGObjectUnref)" % [mprefix]) methodBuffer.writeLine(" fnew(result, $1genericGObjectUnref) # Object" % [mprefix])
methodBuffer.writeLine(" result.impl = " & sym & arglist) methodBuffer.writeLine(" result.impl = " & sym & arglist)
else: else:
assert(gBaseInfoGetType(iface) in {GIInfoType.STRUCT, GIInfoType.UNION}) assert(gBaseInfoGetType(iface) in {GIInfoType.STRUCT, GIInfoType.UNION})
@ -979,16 +1006,19 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
var boxedFreeMeName: string var boxedFreeMeName: string
findFreeProc(iface, gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING) findFreeProc(iface, gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING)
if boxedFreeMeName != "": if boxedFreeMeName != "":
methodBuffer.writeLine(" new(result, $1)" % boxedFreeMeName) methodBuffer.writeLine(" fnew(result, $1)" % boxedFreeMeName)
elif freeMeName == "": elif freeMeName == "":
# assert false # TODO we have to fix this case manually # assert false # TODO we have to fix this case manually
#echo "xCaution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')' #echo "xCaution: No free/unref found for ", ' ', gBaseInfoGetName(iface), " (", sym, ')'
methodBuffer.writeLine(" new(result)") methodBuffer.writeLine(" new(result)")
else: else:
methodBuffer.writeLine(" new(result, $1)" % freeMeName) methodBuffer.writeLine(" fnew(result, $1)" % freeMeName)
methodBuffer.writeLine(" result.impl = " & sym & arglist) methodBuffer.writeLine(" result.impl = " & sym & arglist)
if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING:
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.
if gCallableInfoMayReturnNull(minfo):
methodBuffer.writeLine(" if result.impl.isNil:")
methodBuffer.writeLine(" return nil")
elif false: #else: elif false: #else:
assert gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING assert gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING
methodBuffer.writeLine(" new(result)") methodBuffer.writeLine(" new(result)")
@ -1025,12 +1055,12 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
findFreeProc(info, gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING) findFreeProc(info, gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING)
let h2 = mangleName(gBaseInfoGetName(arg)) let h2 = mangleName(gBaseInfoGetName(arg))
if boxedFreeMeName != "": if boxedFreeMeName != "":
methodBuffer.writeLine(" new(" & h2 & ", " & boxedFreeMeName & ")") methodBuffer.writeLine(" fnew(" & h2 & ", " & boxedFreeMeName & ")")
elif freeMeName == "": elif freeMeName == "":
methodBuffer.writeLine(" new(" & h2 & ")") methodBuffer.writeLine(" new(" & h2 & ")")
#############methodBuffer.writeLine(" $1.ignoreFinalizer = true" % [h2]) #############methodBuffer.writeLine(" $1.ignoreFinalizer = true" % [h2])
else: else:
methodBuffer.writeLine(" new(" & h2 & ", " & freeMeName & ")") methodBuffer.writeLine(" fnew(" & h2 & ", " & freeMeName & ")")
#if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING: #if gCallableInfoGetCallerOwns(minfo) == GITransfer.NOTHING:
if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING: if gArgInfoGetOwnershipTransfer(arg) == GITransfer.NOTHING:
methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") # as we have always to attach one with ARC. methodBuffer.writeLine(" " & h2 & ".ignoreFinalizer = true") # as we have always to attach one with ARC.
@ -1122,10 +1152,12 @@ proc writeMethod(info: GIBaseInfo; minfo: GIFunctionInfo) =
template genBoxedFree = template genBoxedFree =
if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))): if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))):
if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED: if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE and gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED and
gBaseInfoGetName(info) != "VariantType": # we have no g_variant_type_get_gtype
# For example, GVariant has a GType but is not a boxed type # For example, GVariant has a GType but is not a boxed type
#assert(g_type_fundamental(g_registered_type_info_get_g_type(info)) == G_TYPE_BOXED) #assert(g_type_fundamental(g_registered_type_info_get_g_type(info)) == G_TYPE_BOXED)
if gTypeFundamental(gRegisteredTypeInfoGetGType(info)) != G_TYPE_BOXED: if gTypeFundamental(gRegisteredTypeInfoGetGType(info)) != G_TYPE_BOXED:
assert false
if gBaseInfoGetName(info) != "Variant": if gBaseInfoGetName(info) != "Variant":
#echo moduleNamespace, gBaseInfoGetName(info) #echo moduleNamespace, gBaseInfoGetName(info)
assert false assert false
@ -1138,8 +1170,64 @@ template genBoxedFree =
else: else:
output.writeLine(" if not self.ignoreFinalizer:") output.writeLine(" if not self.ignoreFinalizer:")
output.writeLine(" boxedFree(", getTypeProc, "(), ", "cast[ptr " & mangleName(gBaseInfoGetName(info)) & "00](self.impl))") output.writeLine(" boxedFree(", getTypeProc, "(), ", "cast[ptr " & mangleName(gBaseInfoGetName(info)) & "00](self.impl))")
output.writeLine("\nwhen compileOption(\"gc\", \"arc\"):") # the when is not really needed, currently default gc ignores destructor
output.writeLine(" proc `=destroy`*(self: var typeof(" & mangleName(gBaseInfoGetName(info)) & "()[])) =")
output.writeLine(" if not self.ignoreFinalizer and self.impl != nil:")
output.writeLine(" boxedFree(", getTypeProc, "(), ", "cast[ptr " & mangleName(gBaseInfoGetName(info)) & "00](self.impl))")
output.writeLine(" self.impl = nil")
else:
if gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT and
gBaseInfoGetName(info) != "ObjectClass" and gBaseInfoGetName(info) != "TypeFind":
var freeMe: GIFunctionInfo
if gBaseInfoGetType(info) == GIInfoType.UNION:
freeMe = gUnionInfoFindMethod(info, "free")
if freeMe.isNil:
freeMe = gUnionInfoFindMethod(info, "unref")
else:
#if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass":
assert gBaseInfoGetType(info) == GIInfoType.STRUCT
#echo "aaa", info.isNil
#echo "bbb", gStructInfoIsGtypeStruct(info)
#echo "ccc", gStructInfoGetNMethods(info)
#echo gBaseInfoGetName(info)
freeMe = gStructInfoFindMethod(info, "free")
#echo "xxxxxxxx"
if freeMe.isNil:
freeMe = gStructInfoFindMethod(info, "unref")
template genDestroyFreeUnref =
if not callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))):
if gRegisteredTypeInfoGetGType(info) == G_TYPE_NONE or gTypeFundamental(gRegisteredTypeInfoGetGType(info)) != G_TYPE_BOXED or
gBaseInfoGetName(info) == "VariantType": # we have no g_variant_type_get_gtype
#if true:
if gBaseInfoGetType(info) == GIInfoType.UNION or gBaseInfoGetType(info) == GIInfoType.STRUCT and
gBaseInfoGetName(info) != "ObjectClass" and gBaseInfoGetName(info) != "TypeFind":
var freeMe: GIFunctionInfo
if gBaseInfoGetType(info) == GIInfoType.UNION:
freeMe = gUnionInfoFindMethod(info, "free")
if freeMe.isNil:
freeMe = gUnionInfoFindMethod(info, "unref")
else:
#if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass":
assert gBaseInfoGetType(info) == GIInfoType.STRUCT
freeMe = gStructInfoFindMethod(info, "free")
if freeMe.isNil:
freeMe = gStructInfoFindMethod(info, "unref")
if freeMe != nil and gCallableInfoGetNArgs(freeMe) == (if gCallableInfoIsMethod(freeMe): 0 else: 1):
methodBuffer.writeLine("\nwhen compileOption(\"gc\", \"arc\"):")
methodBuffer.writeLine(" proc `=destroy`*(self: var typeof(" & mangleName(gBaseInfoGetName(info)) & "()[])) =")
methodBuffer.writeLine(" if not self.ignoreFinalizer and self.impl != nil:")
methodBuffer.writeLine(" $1(self.impl)" % [$gFunctionInfoGetSymbol(freeMe)])
methodBuffer.writeLine(" self.impl = nil")
proc writeUnion(info: GIUnionInfo) = proc writeUnion(info: GIUnionInfo) =
#if gStructInfoIsGtypeStruct(info) and gBaseInfoGetName(info) != "ObjectClass":
# return # we should not need the class and interface structs
#if gBaseInfoGetName(info).endsWith("Private"): # since v0.5.3 we do not write private structs
# return
#output.writeLine("")
if not suppressType: if not suppressType:
output.writeLine("type") output.writeLine("type")
if callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))): if callerAlloc.contains(($gBaseInfoGetNamespace(info)).toLowerAscii & '.' & mangleName(gBaseInfoGetName(info))):
@ -1159,6 +1247,7 @@ proc writeUnion(info: GIUnionInfo) =
var getTypeProc: string var getTypeProc: string
if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE: if gRegisteredTypeInfoGetGType(info) != G_TYPE_NONE:
#assert false executed for gtk3
getTypeProc = $gRegisteredTypeInfoGetTypeInit(info) getTypeProc = $gRegisteredTypeInfoGetTypeInit(info)
if getTypeProc notin ["intern", "g_gstring_get_type"]: if getTypeProc notin ["intern", "g_gstring_get_type"]:
output.write("\nproc " & getTypeProc & "*(): GType ") output.write("\nproc " & getTypeProc & "*(): GType ")
@ -1170,10 +1259,13 @@ proc writeUnion(info: GIUnionInfo) =
for j in 0.cint ..< gUnionInfoGetNMethods(info): for j in 0.cint ..< gUnionInfoGetNMethods(info):
mseq.add(gUnionInfoGetMethod(info, j)) mseq.add(gUnionInfoGetMethod(info, j))
if freePos < 0 and gBaseInfoGetName(gUnionInfoGetMethod(info, j)) in ["free", "unref"]: if freePos < 0 and gBaseInfoGetName(gUnionInfoGetMethod(info, j)) in ["free", "unref"]:
#assert false executed for gtk3
freePos = j freePos = j
if freePos > 0: swap(mseq[0], mseq[freePos]) if freePos > 0: swap(mseq[0], mseq[freePos])
for mInfo in mseq: for i, mInfo in mseq:
writeMethod(info, minfo) writeMethod(info, minfo)
if i == 0:
genDestroyFreeUnref()
const TargetEntryProx = """ const TargetEntryProx = """
@ -1281,13 +1373,16 @@ proc writeStruct(info: GIStructInfo) =
freePos = j freePos = j
if freePos > 0: swap(mseq[0], mseq[freePos]) if freePos > 0: swap(mseq[0], mseq[freePos])
if mangleName(gBaseInfoGetName(info)) == "TargetEntry": if mangleName(gBaseInfoGetName(info)) == "TargetEntry":
# assert false executed for gtk3
output.writeLine(TargetEntryProx) output.writeLine(TargetEntryProx)
if mangleName(gBaseInfoGetName(info)) == "KeymapKey": if mangleName(gBaseInfoGetName(info)) == "KeymapKey":
output.writeLine(KeymapKeyProx) output.writeLine(KeymapKeyProx)
if mangleName(gBaseInfoGetName(info)) == "PageRange": if mangleName(gBaseInfoGetName(info)) == "PageRange":
output.writeLine(PageRangeProx) output.writeLine(PageRangeProx)
for mInfo in mseq: for i, mInfo in mseq:
writeMethod(info, minfo) writeMethod(info, minfo)
if i == 0:
genDestroyFreeUnref()
template writeSignal() = template writeSignal() =
if gCallableInfoGetNArgs(signalInfo) > 0 or gTypeInfoGetTag(zzzu) != GITypeTag.VOID: if gCallableInfoGetNArgs(signalInfo) > 0 or gTypeInfoGetTag(zzzu) != GITypeTag.VOID:
@ -1325,7 +1420,7 @@ template writeSignal() =
let provider = interfaceProvider[xxx] let provider = interfaceProvider[xxx]
for i in provider: discard mangleType(i) for i in provider: discard mangleType(i)
xxx = xxx & " | " & provider.join(" | ") xxx = xxx & " | " & provider.join(" | ")
signalbuffer.write("proc " & mangleName("sc_" & $gBaseInfoGetName(signalInfo)) & EM & "(self: " & xxx & "; ") signalbuffer.write("\nproc " & mangleName("sc_" & $gBaseInfoGetName(signalInfo)) & EM & "(self: " & xxx & "; ")
if gCallableInfoGetNArgs(signalInfo) > 0 or gTypeInfoGetTag(zzzu) != GITypeTag.VOID: if gCallableInfoGetNArgs(signalInfo) > 0 or gTypeInfoGetTag(zzzu) != GITypeTag.VOID:
#signalbuffer.writeLine(" p: proc (self: ptr " & yyy & "00; " & h & " {.cdecl.}, xdata: pointer = nil, cf: gobject.ConnectFlags = {}): culong =") #signalbuffer.writeLine(" p: proc (self: ptr " & yyy & "00; " & h & " {.cdecl.}, xdata: pointer = nil, cf: gobject.ConnectFlags = {}): culong =")
signalbuffer.writeLine(" p: proc (self: ptr " & yyy & "00; " & h & " {.cdecl.}, xdata: pointer, cf: gobject.ConnectFlags): culong =") signalbuffer.writeLine(" p: proc (self: ptr " & yyy & "00; " & h & " {.cdecl.}, xdata: pointer, cf: gobject.ConnectFlags): culong =")
@ -1343,7 +1438,7 @@ proc writeInterface(info: GIInterfaceInfo) =
output.writeLine(" ", mangleName(gBaseInfoGetName(info)) & "00" & EM & " = object of gobject.Object00") output.writeLine(" ", mangleName(gBaseInfoGetName(info)) & "00" & EM & " = object of gobject.Object00")
output.writeLine(" ", mangleName(gBaseInfoGetName(info)) & EM & " = ref object of gobject.Object") output.writeLine(" ", mangleName(gBaseInfoGetName(info)) & EM & " = ref object of gobject.Object")
let numsig = info.gInterfaceInfoGetNSignals let numsig = info.gInterfaceInfoGetNSignals
if numsig > 0: signalbuffer.writeLine("") #if numsig > 0: signalbuffer.writeLine("")
for j in 0.cint ..< numsig: for j in 0.cint ..< numsig:
let signalInfo = gInterfaceInfoGetSignal(info, j) let signalInfo = gInterfaceInfoGetSignal(info, j)
#let c = gSignalInfoGetClassClosure(signalInfo) #let c = gSignalInfoGetClassClosure(signalInfo)
@ -1387,6 +1482,7 @@ proc writeModifierType(info: GIEnumInfo) =
var val = i.v var val = i.v
if j == 0 and val == 0: continue if j == 0 and val == 0: continue
if j > 0 and i.v == k.v: if j > 0 and i.v == k.v:
assert false
if i.n != k.n: if i.n != k.n:
alias.add(" " & tname & i.n.capitalizeAscii & EM & " = " & tname & '.' & k.n) alias.add(" " & tname & i.n.capitalizeAscii & EM & " = " & tname & '.' & k.n)
continue continue
@ -1394,6 +1490,7 @@ proc writeModifierType(info: GIEnumInfo) =
output.writeLine(" ", i.n, " = ", val) output.writeLine(" ", i.n, " = ", val)
k = i k = i
if alias.len > 0: if alias.len > 0:
assert false
output.writeLine("\nconst") output.writeLine("\nconst")
for i in alias: for i in alias:
output.writeLine(i) output.writeLine(i)
@ -1469,6 +1566,7 @@ proc writeEnum(info: GIEnumInfo) =
proc writeObj(info: GIObjectInfo) = proc writeObj(info: GIObjectInfo) =
if gBaseInfoGetName(info).endsWith("Private"): if gBaseInfoGetName(info).endsWith("Private"):
assert false
return return
assert(gBaseInfoGetType(info) == GIInfoType.OBJECT) assert(gBaseInfoGetType(info) == GIInfoType.OBJECT)
let class = gObjectInfoGetClassStruct(info) let class = gObjectInfoGetClassStruct(info)
@ -1567,7 +1665,7 @@ proc writeObj(info: GIObjectInfo) =
output.write("\nproc " & getTypeProc & "*(): GType ") output.write("\nproc " & getTypeProc & "*(): GType ")
output.writeLine("{.importc, " & libprag & ".}") output.writeLine("{.importc, " & libprag & ".}")
let numsig = info.gObjectInfoGetNSignals let numsig = info.gObjectInfoGetNSignals
if numsig > 0: signalbuffer.writeLine("") #if numsig > 0: signalbuffer.writeLine("")
for j in 0.cint ..< numsig: for j in 0.cint ..< numsig:
let signalInfo = gObjectInfoGetSignal(info, j) let signalInfo = gObjectInfoGetSignal(info, j)
let c = gSignalInfoGetClassClosure(signalInfo) let c = gSignalInfoGetClassClosure(signalInfo)
@ -1581,12 +1679,20 @@ proc writeObj(info: GIObjectInfo) =
let mInfo = gObjectInfoGetMethod(info, j) let mInfo = gObjectInfoGetMethod(info, j)
writeMethod(info, minfo) writeMethod(info, minfo)
if class != nil and not allSyms.contains(mangleName(gBaseInfoGetName(class))): if class != nil and not allSyms.contains(mangleName(gBaseInfoGetName(class))):
assert false
classList.add(class) classList.add(class)
ct.inc($gBaseInfoGetName(info), cnt + 1) ct.inc($gBaseInfoGetName(info), cnt + 1)
if gBaseInfoGetName(info) == "Object" and moduleNamespace == "gobject": if gBaseInfoGetName(info) == "Object" and moduleNamespace == "gobject":
output.writeLine("type\n Object* = ref object of RootRef") output.writeLine("type\n Object* = ref object of RootRef")
output.writeLine(" impl*: ptr Object00") output.writeLine(" impl*: ptr Object00")
output.writeLine(" ignoreFinalizer*: bool") output.writeLine(" ignoreFinalizer*: bool")
if gObjectInfoGetFundamental(info) == GFalse: # guess work, ignore fake GObjects like GParamSpec and such
output.writeLine("\nwhen compileOption(\"gc\", \"arc\"):")
output.writeLine(" proc `=destroy`*(self: var typeof(" & mangleName(gBaseInfoGetName(info)) & "()[])) =")
output.writeLine(" if not self.ignoreFinalizer and self.impl != nil:")
output.writeLine(" g_object_remove_toggle_ref(self.impl, toggleNotify, addr(self))")
output.writeLine(" self.impl = nil")
proc extractFromUnion(tag: GITypeTag; arg: GIArgumentObj): string = proc extractFromUnion(tag: GITypeTag; arg: GIArgumentObj): string =
result = result =
case tag: case tag:
@ -1676,6 +1782,7 @@ proc processInfo(i: GIBaseInfo) =
elif gBaseInfoGetType(i) == GIInfoType.Boxed: elif gBaseInfoGetType(i) == GIInfoType.Boxed:
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
else: else:
assert(false) assert(false)
@ -1693,24 +1800,18 @@ proc seq2cstringArray*(s: openarray[string]; a: var cstringArray): cstringArray
const GTK_SOURCE_EPI = """ const GTK_SOURCE_EPI = """
proc nogetView(builder: Builder; name: string): View =
new result
let gt = g_type_from_name("GSource")
assert(gt != 0)
result.impl = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
assert(toBool(g_type_check_instance_is_a(cast[ptr TypeInstance00](result.impl), gt)))
proc getView*(builder: Builder; name: string): View = proc getView*(builder: Builder; name: string): View =
#let gt = g_type_from_name("Gtk$1") # this worked also! #let gt = g_type_from_name("Gtk$1") # this worked also!
#let gt = $2 #let gt = $2
let gt = g_type_from_name("GSource") let gt = g_type_from_name("GSource")
assert(gt != g_type_invalid_get_type()) assert(gt != g_type_invalid_get_type())
let gobj = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name) let gobj = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
assert(gobj != nil)
if g_object_get_qdata(gobj, Quark) != nil: if g_object_get_qdata(gobj, Quark) != nil:
result = cast[type(result)](g_object_get_qdata(gobj, Quark)) result = cast[type(result)](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj) assert(result.impl == gobj)
else: else:
new(result, gtksource.finalizeGObject) fnew(result, gtksource.finalizeGObject)
result.impl = gobj result.impl = gobj
result.ignoreFinalizer = true result.ignoreFinalizer = true
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[])) g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
@ -1728,7 +1829,7 @@ proc invalidateRect*(self: Window; rect: ptr Rectangle = nil; invalidateChildren
gdk_window_invalidate_nilrect(cast[ptr Window00](self.impl), rect, gboolean(invalidateChildren)) gdk_window_invalidate_nilrect(cast[ptr Window00](self.impl), rect, gboolean(invalidateChildren))
proc fixednewCursorFromName*(display: Display; name: string): Cursor = proc fixednewCursorFromName*(display: Display; name: string): Cursor =
new(result, gdk.finalizeGObject) fnew(result, gdk.finalizeGObject)
result.impl = gdk_cursor_new_from_name(cast[ptr Display00](display.impl), cstring(name)) result.impl = gdk_cursor_new_from_name(cast[ptr Display00](display.impl), cstring(name))
GC_ref(result) GC_ref(result)
discard g_object_ref_sink(result.impl) discard g_object_ref_sink(result.impl)
@ -1821,7 +1922,7 @@ proc newFileChooserDialog*(title: string = ""; parent: Window = nil; action: Fil
result = cast[type(result)](g_object_get_qdata(gobj, Quark)) result = cast[type(result)](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj) assert(result.impl == gobj)
else: else:
new(result, $1.finalizeGObject) fnew(result, $1.finalizeGObject)
result.impl = gobj result.impl = gobj
GC_ref(result) GC_ref(result)
discard g_object_ref_sink(result.impl) discard g_object_ref_sink(result.impl)
@ -1837,7 +1938,7 @@ proc initFileChooserDialog*[T](result: var T; title: string = ""; parent: Window
result = cast[type(result)](g_object_get_qdata(gobj, Quark)) result = cast[type(result)](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj) assert(result.impl == gobj)
else: else:
new(result, $1.finalizeGObject) fnew(result, $1.finalizeGObject)
result.impl = gobj result.impl = gobj
GC_ref(result) GC_ref(result)
discard g_object_ref_sink(result.impl) discard g_object_ref_sink(result.impl)
@ -1912,12 +2013,13 @@ proc main(namespace: string; version: cstring = nil) =
let libs = gi.gIrepositoryGetSharedLibrary(namespace) let libs = gi.gIrepositoryGetSharedLibrary(namespace)
output.writeLine("# libraries:") output.writeLine("# libraries:")
output.writeLine("# ", libs) output.writeLine("# ", libs)
output.writeLine("{.deadCodeElim: on, warning[UnusedImport]: off.}") # gmodule, xlib, cairo #output.writeLine("{.deadCodeElim: on, warning[UnusedImport]: off.}") # gmodule, xlib, cairo
output.writeLine("{.warning[UnusedImport]: off.}") # gmodule, xlib, cairo
output.writeLine(importedModules) output.writeLine(importedModules)
var Lib = if libs.isNil: "" else: ($libs).split(',', 2)[0] var Lib = if libs.isNil: "" else: ($libs).split(',', 2)[0]
if namespace == "PangoCairo" and Lib.startsWith( if namespace == "PangoCairo" and Lib.startsWith(
"libpango-"): Lib = Lib.replace("libpango-", "libpangocairo-") # GI bug? "libpango-"): Lib = Lib.replace("libpango-", "libpangocairo-") # GI bug?
output.writeLine("const Lib* = \"$1\"" % Lib) output.writeLine("const Lib = \"$1\"" % Lib)
output.writeLine("{.pragma: libprag, cdecl, dynlib: Lib.}") output.writeLine("{.pragma: libprag, cdecl, dynlib: Lib.}")
if namespace == "GObject": # declare array types to make it compile -- procs using these will need special care! if namespace == "GObject": # declare array types to make it compile -- procs using these will need special care!
output.writeLine("type\n GCallback* = proc () {.cdecl.}") output.writeLine("type\n GCallback* = proc () {.cdecl.}")
@ -1984,6 +2086,15 @@ proc main(namespace: string; version: cstring = nil) =
output.writeLine("\nproc boxedFree(boxedType: GType; boxed: pointer) {.") output.writeLine("\nproc boxedFree(boxedType: GType; boxed: pointer) {.")
output.writeLine(" importc: \"g_boxed_free\", gobjectlibprag.}") output.writeLine(" importc: \"g_boxed_free\", gobjectlibprag.}")
output.writeLine("""
#proc fnew*[T](a: var ref T; finalizer: proc (x: ref T)) =
template fnew*(a: untyped; finalizer: untyped) =
when compileOption("gc", "arc"):
new(a)
else:
new(a, finalizer)
""")
output.writeLine(""" output.writeLine("""
proc int32ArrayZT2seq*(p: pointer): seq[int32] = proc int32ArrayZT2seq*(p: pointer): seq[int32] =
let a = cast[ptr UncheckedArray[int32]](p) let a = cast[ptr UncheckedArray[int32]](p)
@ -2103,11 +2214,11 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] =
if namespace notin ["GObject", "GLib", "xlib", "GModule"]: if namespace notin ["GObject", "GLib", "xlib", "GModule"]:
output.writeLine("\nproc finalizeGObject*[T](o: ref T) =") output.writeLine("\nproc finalizeGObject*[T](o: ref T) =")
output.writeLine("\n if not o.ignoreFinalizer:") output.writeLine(" if not o.ignoreFinalizer:")
output.writeLine(" gobject.g_object_remove_toggle_ref(o.impl, gobject.toggleNotify, addr(o[]))") output.writeLine(" gobject.g_object_remove_toggle_ref(o.impl, gobject.toggleNotify, addr(o[]))")
output.writeLine("\nproc genericGObjectUnref*[T](self: ref T) =") #output.writeLine("\nproc genericGObjectUnref*[T](self: ref T) =")
output.writeLine(" if not self.ignoreFinalizer:") #output.writeLine(" if not self.ignoreFinalizer:")
output.writeLine(" gobject.g_object_unref(cast[ptr gobject.Object00](self.impl))") #output.writeLine(" gobject.g_object_unref(cast[ptr gobject.Object00](self.impl))")
var n = gi.gIrepositoryGetNInfos(namespace) var n = gi.gIrepositoryGetNInfos(namespace)
var s: seq[GIBaseInfo] var s: seq[GIBaseInfo]
@ -2211,6 +2322,7 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] =
i = s.pop i = s.pop
delayedSyms.insert(i) delayedSyms.insert(i)
if classList.len > 0: if classList.len > 0:
assert false
delayedSyms.insert(classList.pop) delayedSyms.insert(classList.pop)
unp.setLen(0) unp.setLen(0)
for k in delayedSyms: for k in delayedSyms:
@ -2238,7 +2350,9 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] =
methodBuffer = newStringStream() methodBuffer = newStringStream()
signalBuffer = newStringStream() signalBuffer = newStringStream()
unp = delayedSyms unp = delayedSyms
for t in unp.combinations(a + 1): #for t in unp.combinations(a + 1): # works fine with default GC
var hhh = toSeq(unp.combinations(a + 1)) # nedded for --gc:arc
for t in hhh:
var pos = output.getPosition var pos = output.getPosition
var supmodpos3 = supmod3.getPosition var supmodpos3 = supmod3.getPosition
var supmodpos4 = supmod4.getPosition var supmodpos4 = supmod4.getPosition
@ -2251,6 +2365,7 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] =
if gBaseInfoGetType(k) notin {GIInfoType.INTERFACE, GIInfoType.OBJECT, GIInfoType.STRUCT, GIInfoType.UNION} and if gBaseInfoGetType(k) notin {GIInfoType.INTERFACE, GIInfoType.OBJECT, GIInfoType.STRUCT, GIInfoType.UNION} and
not isCallbackInfo(k): not isCallbackInfo(k):
h = true h = true
assert false
if h: continue if h: continue
output.writeLine("type") output.writeLine("type")
for k in t: for k in t:
@ -2282,6 +2397,7 @@ proc uint8ArrayZT2seq*(p: pointer): seq[uint8] =
suppressRaise = true suppressRaise = true
output.writeLine("# === remaining symbols:") # in best case there is nothing left output.writeLine("# === remaining symbols:") # in best case there is nothing left
for i in delayedSyms: for i in delayedSyms:
assert false
processInfo(i) processInfo(i)
if externInterfaces.len > 0: if externInterfaces.len > 0:
output.writeLine( output.writeLine(
@ -2327,15 +2443,15 @@ proc init* =
output.write( output.write(
""" """
proc get$1*(builder: Builder; name: string): $1 = proc get$1*(builder: Builder; name: string): $1 =
#let gt = g_type_from_name("Gtk$1") # this worked also!
let gt = $2 let gt = $2
assert(gt != g_type_invalid_get_type()) assert(gt != g_type_invalid_get_type())
let gobj = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name) let gobj = gtk_builder_get_object(cast[ptr Builder00](builder.impl), name)
assert(gobj != nil)
if g_object_get_qdata(gobj, Quark) != nil: if g_object_get_qdata(gobj, Quark) != nil:
result = cast[type(result)](g_object_get_qdata(gobj, Quark)) result = cast[type(result)](g_object_get_qdata(gobj, Quark))
assert(result.impl == gobj) assert(result.impl == gobj)
else: else:
new(result, $3.finalizeGObject) fnew(result, $3.finalizeGObject)
result.impl = gobj result.impl = gobj
result.ignoreFinalizer = true result.ignoreFinalizer = true
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[])) g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
@ -2391,11 +2507,20 @@ proc get$1*(builder: Builder; name: string): $1 =
o.write(output.data) o.write(output.data)
o.close() o.close()
output.close output.close
echo "Remaining delayed methods: ", delayedMethods.len stdout.write("Remaining delayed methods: ", delayedMethods.len)
if delayedMethods.len == 0:
echo " (Fine!)"
else:
echo " delayed:"
for el in delayedMethods: for el in delayedMethods:
echo gBaseInfoGetName(el[1]) echo gBaseInfoGetName(el[1])
proc launch() = proc launch() =
when compileOption("gc", "arc"):
echo "GC is arc"
when compileOption("gc", "refc"):
echo "GC is refc"
ISGTK3 = paramCount() == 0 # we have to launch the generator two times, as typelibs can not be unloaded! ISGTK3 = paramCount() == 0 # we have to launch the generator two times, as typelibs can not be unloaded!
supmod3 = newStringStream() supmod3 = newStringStream()
supmod3.writeLine("const\n SCA = [") supmod3.writeLine("const\n SCA = [")
@ -2472,5 +2597,5 @@ proc launch() =
o.close() o.close()
supmod4.close supmod4.close
launch() # depStr TODO launch()
# 2476 lines # 2601 lines construct benil