$ grep -A24 "newGFileTmp" ~/.nimble/pkgs/gintro-#head/gintro/gio.nim
proc newGFileTmp*(tmpl: cstring = ""; iostream: var FileIOStream): GFile =
var gerror: ptr glib.Error
let gobj = g_file_new_tmp(safeStringToCString(tmpl), cast[var ptr FileIOStream00](addr iostream.impl), addr gerror)
if gerror != nil:
let msg = $gerror.message
g_error_free(gerror[])
raise newException(GException, msg)
let qdata = g_object_get_qdata(gobj, Quark)
if qdata != nil:
result = cast[type(result)](qdata)
assert(result.impl == gobj)
else:
fnew(result, gio.finalizeGObject)
result.impl = gobj
GC_ref(result)
if g_object_is_floating(result.impl).int != 0:
discard g_object_ref_sink(result.impl)
g_object_add_toggle_ref(result.impl, toggleNotify, addr(result[]))
g_object_unref(result.impl)
assert(g_object_get_qdata(result.impl, Quark) == nil)
g_object_set_qdata(result.impl, Quark, addr(result[]))
Access to iostream.impl is wrong, as FileIOStream is a Nim proxy object which we had to allocate before use. I think I have to fix it manually, teaching the bindings generator to handle it fully correct seems to be difficult.
Before I try to fix that: What is the iostream instance in the g_file_new_tmp() call, for what is it needed and do we have to free it? I think for writing to the tmp file we do need only the returned GFile, but not the iostream instance?
The GIOStream is a second return value together with the proper GFile return value. It’s an (out) parameter, and it can be used for writing/reading that temporary file that was created here while the GFile is basically its “path”. When calling the function you’d pass in a pointer to a pointer to where that stream should be stored, and it’s stored there (transfer full).
In Python and Rust such function works by returning a tuple with the GFile and the stream in the successful, non-error case.
This has to be handled the same as all other (out) parameters, it’s not really special so if this is confusing the bindings generator then you’ll probably also end up generating wrong bindings for other similar functions too.
This tells you that it’s an (out) parameter (i.e. yet another return value), and that it’s (transfer full) (you own the reference that was returned and have to unref it at some point).
In addition because this function has a GError parameter there are further semantics: if NULL is returned for the proper return value (or FALSE for functions returning bools) then it’s considered an error and the GError out parameter will be set instead (and the stream will not be set).
I’m waiting for some C++ code to compile right now
Ah yes indeed. I was a bit lazy this morning, and maybe a bit confused about the fact that
transfer-ownership=“full” for iostream is not mentioned in the API docs.
But as this info is available in the gobject-introspection data, my generator script has this info and often uses it. I guess the current problem is that my bindings generator script handles Constructors and plain functions very differently, for constructors I seem to expect always that there are no other out parameters involved. I think we had a similar issue with one more function some months ago. I have to fix that.