It is a bit hard to explain unfortunately. The problem are the GTK callbacks 
and signals. In C we can connect to a signal name given as a string providing a 
callback proc and a pointer to arbitrary data. In higher level languages we try 
to archive type safety, so we have to ensure that our provided data match our 
proc signature.

My nim-gi module 
([https://github.com/StefanSalewski/nim-gi2](https://github.com/StefanSalewski/nim-gi2))
 can generate already some nice bindings (at least for Linux AMD64 and GTK 
3.22), and with some help of Mr J. Mansour I created a first working test with 
a connect macro which looks like this:
    
    
    # TODO: this macro will be moved to library module!
    macro connect(widget: Widget; signal: string; p: typed; arg: typed): 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)
      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`) 
=
          `scName`(self, `procNameCdecl`, cast[pointer](a))
        `procName`(`widget`, `p`, `arg`)
    

and is called like
    
    
      connect(button1, "clicked", clickd, "Hello")
    
    

(Full code at 
[https://github.com/StefanSalewski/nim-gi2](https://github.com/StefanSalewski/nim-gi2))

I am not sure if the macro has good shape, but it seems to work. Indeed it 
should not really work -- the passed in string "Hello" is collected by the GC 
at some time...

So what we need is a way to make that arbitrary typed data parameter 
persistent. For ref to objects a GC_ref would do. All other data which are not 
refs should need a copy which is then passed to the callback. So question is: 
How can I check if the parameter is a ref on which I can call GR_ref. And if 
not a ref, how can I do best a persistent copy, maybe a deep copy?

In best case it should be even possible to free that data later again, because 
GTK allows disconnecting of callbacks. But that is rarely used, and the data is 
generally small, so not much Ram is wasted. 

Reply via email to