#define GTK_TYPE_BUTTON (gtk_button_get_type ())
So they can write GTK_TYPE_BUTTON without () to get the VALUE of gtk_button_get_type() function. We do not really need that, so I simple skip that for the initial wrapper version. In current gtk2 wrapper they use
proc TYPE_BUTTON*(): GType = result = button_get_type()
which in my opinion is not very smart, it is an alias for the function, not for the value. To get the value we still have to write TYPE_BUTTON_BOX() with the bracket. And the same alias wound be available by
const TYPE_BUTTON* = button_get_type
Now my problem: Maybe I will provide a template for GType values which can be used without bracket, as in C code:
proc stack_get_type*(): GType {.importc: "gtk_stack_get_type".}
template type_stack*:GType =
#stack_get_type()
GType(0)
template stack1*(obj: expr): expr =
(g_type_check_instance_cast(obj, type_stack(), StackObj))
template stack2*(obj: expr): expr =
var h = type_stack
(g_type_check_instance_cast(obj, h, StackObj))
template stack3*(obj: expr): expr =
(g_type_check_instance_cast(obj, type_stack, StackObj))
template stack1 and template stack2 compiles fine, but template stack3 gives an error. I think the reason is, that g_type_check_instance_cast() is again a template, with expr parameters. So compiler can not know if it should pass the value of type_stack template or the template itself. For the wrapper that is no problem, I can always use code like version 1 or 2, or I can change parameter type of second parameter of template g_type_check_instance_cast() from expr to GType. The real question is: Is there a pragma or something similar that make it clear to the compiler that the name of the template (type_stack) always stands for the value, and never for the template itself?
And a related question: May something like
const type_stack* = stack_get_type()
work? Here stack_get_type() is a gtk function, and it seems not to work. I tried nosideeffect pragma for stack_get_type(), but it seems not to help. Let instead of const may work (not yet tested) but that should consume some memory for all the types, similar as vars? (I have to admit that calling the gtk get_type() functions during compiling may not work at all, because init_gtk() is not called. I gues it would work, but I have to inspect the C code...)
[EDIT]
let Type_stack*:GType =
stack_get_type()
indeed compiles fine. But I don't know if I should really like that -- much overhead only to offer users an value alias, which they generally do not need...
type
GType = distinct int
proc stack_get_type*(): GType = discard
template type_stack*: GType = GType(0)
template g_type_check_instance_cast(a, b: expr) = discard
template stack1*(obj: expr): expr =
(g_type_check_instance_cast(obj, type_stack()))
template stack2*(obj: expr): expr =
(g_type_check_instance_cast(obj, type_stack))
template stack3*(obj: expr): expr =
var h = type_stack
(g_type_check_instance_cast(obj, h))
stack1(unknown)
stack2(unknown)
stack3(unknown)
Works for me and while the spec doesn't mention it, nullary templates are always expanded, there is no need to annotate anything here. So there must be something else problematic with your code.
Thanks for testing.
So there must be something else problematic with your code.
Yes, and I have no idea currently.
A copy of the files is available at http://ssalewski.de/tmp/temptest/ as single files or full set in a tar archive. I have just downloaded the tar, extracted and
temptest $ nim c main.nim exampleappwin.nim(156, 18) Error: type mismatch: got (GTypeInstance, proc (): expr) but expected one of: gobject.g_type_check_instance_cast(instance: expr, g_type: expr, c_type: expr) gobject.g_type_check_instance_cast(instance: GTypeInstance, iface_type: GType)
I have not really an idea what generates this compiler error. There is an template and a proc with same name, but only two parameters. I think that should be no problem. Sorry, files are not cleaned up yet... Nim Compiler Version 0.11.3 (2015-08-11) [Linux: amd64] (Testing should work with Linux, for Windows I am not really sure, some files are simple extracted from my working copy of the gtk3 wrappers.)
I also tested the idea with let from above -- that compiles fine but program does not work. GType values must be asked for at runtime I think.
There is an template and a proc with same name, but only two parameters. I think that should be no problem.
Er, but surely that is the problem... Maybe your wrapper should not exploit every corner case of the language? ;-)
template g_type_check_instance_cast*(instance, g_type, c_type: expr): expr =
(g_type_cic(instance, g_type, c_type))
proc g_type_check_instance_cast*(instance: GTypeInstance;
iface_type: GType): GTypeInstance {.
importc: "g_type_check_instance_cast", libgobj.}
The proc has two parameters, the template three.
I do admit that the gtk related macros can be hard -- for me and the compiler. And the case insensitivity of Nim makes it even harder, in C the macros were wrttten in caps. I started writing the templates in caps too, as older versions of c2nim did. But that gave other name conflicts, for example with type names. While the gtk3 wrapper is already generated with latest c2nim, the gobject one is still generated with an older version. In the next months I will try to migrate all to the latest c2nim, maybe that version is so smart that it can avoid problems as this? (And generally I will try to convert templates to plain (inline) procs when possible, that should further reduce trouble.)
[EDIT]
Renaming the proc does not really help, now I get:
exampleappwin.nim(156, 18) Error: type mismatch: got (GTypeInstance, proc (): expr) but expected one of: gobject.g_type_check_instance_cast_proc(instance: GTypeInstance, iface_type: GType)
Again -- no idea on my side. :-(
Unfortunately I have not really an idea how your last comment is related to the actual problem.
But after some more testing I found that changing true to false in this gobject code fixed the compile problem:
when false: # when not(defined(G_DISABLE_CAST_CHECKS)):
template g_type_cic*(ip, gt, ct: expr): expr =
(cast[ptr ct](g_type_check_instance_cast(cast[GTypeInstance](ip), gt)))
template g_type_ccc*(cp, gt, ct: expr): expr =
(cast[ptr ct](g_type_check_class_cast(cast[GTypeClass](cp), gt)))
else:
template g_type_cic*(ip, gt, ct: expr): expr =
(cast[ptr ct](ip))
template g_type_ccc*(cp, gt, ct: expr): expr =
(cast[ptr ct](cp))
I have not really an idea what is wrong, but at least I have located it. Maybe with g_type_cic the nesting of templates is too deep?
type
GType = int
type StackObj = object
i: int
type
GTypeInstance* = ptr RootObj
var
priv: pointer
proc xg_type_check_instance_cast*(instance: GTypeInstance;
iface_type: GType): GTypeInstance =
cast[GTypeInstance](0)
#discard
template g_type_check_instance_cast*(instance, g_type, c_type: expr): expr =
(g_type_cic(instance, g_type, c_type))
template g_type_cic*(ip, gt, ct: expr): expr =
(cast[ptr ct](xg_type_check_instance_cast(cast[GTypeInstance](ip), gt)))
proc stack_get_type*(): GType =
0
template type_stack*(): expr =
(stack_get_type())
template stack*(obj: expr): expr =
(g_type_check_instance_cast(obj, type_stack, StackObj))
var hhh = stack(priv)
um.nim(34, 16) Error: type mismatch: got (GTypeInstance, proc (): expr) but expected one of: um.xg_type_check_instance_cast(instance: GTypeInstance, iface_type: GType) And with type_stack() it compiles fine.
type
GType = int
type StackObj = object
i: int
type
GTypeInstance* = ptr RootObj
var
priv: pointer
template g_type_check_instance_cast*(instance: expr; g_type: expr; c_type: expr): expr =
var hhh = g_type
(g_type_cic(instance, g_type, c_type))
template g_type_cic*(ip: expr; gt: GType; ct: expr): expr =
(cast[ptr ct](0))
template xtype_stack(): GType =
0
template stock*(obj: expr): expr =
(g_type_check_instance_cast(obj, xtype_stack, StackObj))
var hhh = stock(priv)
um.nim(28, 16) template/generic instantiation from here um.nim(15, 14) Error: type mismatch: got (pointer, proc (): GType, typedesc[StackObj]) but expected one of: um.g_type_cic(ip: expr, gt: GType, ct: expr)
got proc(): There is no proc in that source code. When using var hhh for g_type in g_type_check_instance_cast it compiles fine. I hope the same fix will work in the gtk3 wrapper also. Maybe I should install a new Nim version, I still have Nim Compiler Version 0.11.3 (2015-08-11) [Linux: amd64]
Some days ago I tried to build an older gtk app with the new 3.20 wrapper. Seems that the compiler behaves still identical when compiling templates with a shape similar to the above example or the github issue https://github.com/nim-lang/Nim/issues/3447
Finding the location of the error can be really hard for a larger source text with many templates, I tried two hours without an idea, before a diff with gobject.nim 3.15 showed me the var hhh = g_type workaround applied one year ago. Dominik labeled the github issue "error messages".
But what is really wrong with the code above? There may exist more similar problems in gobject.nim, which become visible only if someone uses the templates, and then locating the error is hard again. What can I do to prevent such problems (I will not insert a line like "var hhh = g_type" in each template.)