As Aporia compiles again with GTK3, I have started looking at its code thinking about some cleanup. Some addr operators have vanished already because I used var parameters in GTK3 when appropriate. What is left:
From GTK3 warpper
proc get_text*(start: TextIter; `end`: TextIter): cstring {.
importc: "gtk_text_iter_get_text", libgtk.}
From Aporia:
var endIter: TTextIter
var text = $buffer.getText(addr(startIter), addr(endIter), false)
https://developer.gnome.org/gtk3/stable/GtkTextIter.html#gtk-text-iter-get-text
So TextIter is generally an object on the stack, not a pointer. I really think that something like
proc get_text*(start: TextIterObj; `end`: TextIterObj): cstring {.
importc: "gtk_text_iter_get_text", libgtk.}
will not work for wrapper code? Using var parameters may work, but here the parameters are not intended to be modified, so that would be not really correct. So I have to write a proc or templates which takes TextIters as object and calls the wrapper proc with its adresses?
I'm not sure I understand (so I'll summarize what I think and then jump on me if I'm not) - TextIter is a pointer type (ptr) which points to an object of type TextIterObj.
Aporia shouldn't be calling with TextIterObj directly - it's using (GTK 2's) TTextIter instead, which has the same layout as TextIterObj, and then calling with the address (as you have above) of startIter/endIter (essentially using an unnamed pointer type).
The GTK3 API gtk_text_iter_get_text() accepts two pointers which it promises not to modify... hmmm.
So the issue is that Aporia won't compile when ported to GTK3 because ptr TextIterObj != ptr TTextIter in the type system, but they are (behind the scenes) pointers to objects of the same type? TextIter should be equivalent to addr(TTextIter), so could you do something like:
proc get_text*[T: TextIter | ptr TTextIter](s,e: T)=
result = get_text_wrapped(cast[TextIter](s),cast[TextIter](e))
# with get_text_wrapped the same as your original:
proc get_text_wrapped*(start: TextIter; `end`: TextIter): cstring {.
importc: "gtk_text_iter_get_text", libgtk.}
because ptr TextIterObj != ptr TTextIter
TTextIter is the legacy Object name for TextIterObj -- they are identical, mapping of TTextIter to TextIterObj is done by the deprecated statement of Nim. So Aporia compiles and partly works with GTK3 already, but having addr statements in the Aporia code is ugly. I have to think about it still...
Declare TextIterObj as {.byref.} perhaps?
It seems that {.byref.} pragma can be applied to objects -- which is fine. But would it be even more useful if we can apply it to procs or proc parameters too?
And finally I wonder -- Nim is a smart language -- so how smart can procs be? May a wrapper proc accept an object and a ptr to that object also. For C lib wrapper procs that may be useful I guess.
Unfortunately there are a lot procs like gtk_text_iter_get_text() which may be called with a TextIter or a TextIterObj -- I think TextIterObj is by far the most important case. TextIterObj should work as parameter when I mark the TextIterObj with byref pragma, but I should still provide procs for ptr parameters. So much code grow/duplication.
My current idea: Use a new type instead of TextIter for these proc parameters and provide converters from TextIter and TextIterObj to that new type. Similar as Nim does it from Nim strings to cstrings. New type, because there should be only automatic conversion for wrapper proc calls, and no direct conversion between TextIter and TextIterObj.