Well, I have a working solution. I can pass a string, an int, and object from
the stack to the callback and it works. (Removing a button and reinserting does
not work currently, but that is a different problem.) But I still wonder why I
have to use the strange name(type(arg)) way to get the type of the callback
parameter, and getType(arg) in macro does not work. Of course this code always
makes a deep copy of the callback parameter, that wasted some ram.
# plain test for high level gi based GTK3 Nim wrapper
# https://github.com/StefanSalewski/nim-gi2
import gtk, glib, gobject
import macros
import strutils
import typetraits
type
ParObj = object
x: float
type
XButton = ref object of Button
x: int
# TODO: will be moved to library module!
let Quark = g_quark_from_static_string("NimGIQuark")
# TODO: will be moved to library module!
proc initWithArgv*() =
var
cmdLine{.importc.}: cstringArray
cmdCount{.importc.}: cint
gtk.gtk_init(cmdCount, cmdLine)
proc clicked(button: XButton; arg: ParObj) =
echo arg.x
echo button.x
proc clicked2(button: Button; arg: string) =
echo arg
proc clicked3(button: Button; arg: int) =
echo arg
proc bye(w: Window; arg: string) =
mainQuit()
echo arg
var ProcID: int
# TODO: this macro will be moved to library module!
macro mconnect(widget: Widget; signal: string; p: untyped; arg: typed; rrt:
string): typed =
inc(ProcID)
let wt = getType(widget) # widget type
#let at = getType(arg) # argument type
let signalName = ($signal).replace("-", "_") # maybe we should just use
plain proc names
let procNameCdecl = newIdentNode("connect_for_signal_cdecl_" & signalName
& $ProcID)
let procName = newIdentNode("connect_for_signal_" & signalName & $ProcID)
let scName = newIdentNode("sc" & signalName)
let at = newIdentNode($rrt)
result = quote do:
proc `procNameCdecl`(button: ptr Object00 , data: pointer) {.cdecl.} =
var h: pointer = g_object_get_qdata(button, Quark)
`p`(cast[`wt`](h), cast[`at`](data))
proc `procName`(self: `wt`; p: proc (self: `wt`, arg: `at`); a: `at`)
=
var ar: ref `at`
new(ar)
deepCopy(ar[], a)
GC_ref(ar)
`scName`(self, `procNameCdecl`, cast[pointer](ar[]))
`procName`(`widget`, `p`, `arg`)
template connect(widget: Widget; signal: string; p: untyped; arg: typed) =
mconnect(widget, signal, p, arg, name(type(arg)))
proc work =
var window: Window = newWindow(WindowType.topLevel)
window.setTitle("First Test")
window.setBorderWidth(10)
var
box = newBox(Orientation.vertical, 0)
button1: XButton
button2 = newButton("Wrapper")
button3 = newButton("Int button")
parObj: ParObj
parObj.x = 3.1415
initButton(button1)
button1.setLabel("Nim GI")
button1.x = 99
connect(button1, "clicked", clicked, parObj)
connect(button3, "clicked", clicked3, 1234567)
connect(window, "destroy", bye, "Bye")
button2.connect("clicked", (proc(button: Button; arg: string) = echo
arg), "Bye")
box.add(button1)
box.add(button2)
box.add(button3)
#box.remove(button2) # this does not work currently
#box.add(button2)
window.add(box)
window.showAll
let p = button1.getParent
assert(p == box)
proc main() =
initWithArgv()
work()
GC_fullCollect()
gtk.gtkMain()
main()