GtkArg typesafety



On Mon, Jan 03, 2000 at 06:04:18PM -0500, Havoc Pennington wrote:
> I think we should always have _new() for the common cases. Arguments
> require reading more documentation, aren't typesafe, and are less
> convenient if you are doing something really common.

We can do a little bit about the typesafety.  I've just made a change to gob
(in cvs, not released yet) that for each argument that the object has it also
makes a wrapper macro that does a cast.  This isn't complete type safety, but
does solve a lot of the type problems.

So for the example of my-person.gob (object MyPerson) which has three
arguments, "name", "dob", "dod".  So I have gob define the following macros:

#define MY_PERSON_ARG_NAME(arg)    	"name",(gpointer)(arg)
#define MY_PERSON_GET_ARG_NAME(arg)	"name",(gpointer *)(arg)
#define MY_PERSON_ARG_DOB(arg)    	"dob",(glong)(arg)
#define MY_PERSON_GET_ARG_DOB(arg)	"dob",(glong *)(arg)
#define MY_PERSON_ARG_DOD(arg)    	"dod",(glong)(arg)
#define MY_PERSON_GET_ARG_DOD(arg)	"dod",(glong *)(arg)

They are all READWRITE arguments.  If one was read only or write only, only
that approriate macro would be added.  

SO for setting, you'd use

  gtk_object_set(GTK_OBJECT(person),
	         MY_PERSON_ARG_NAME("Foo"),
	         MY_PERSON_ARG_DOB(time(NULL)),
	         MY_PERSON_ARG_DOD(0),
                 NULL);

for getting you'd use

  glong dob;

  gtk_object_get(GTK_OBJECT(person),
	         MY_PERSON_GET_ARG_DOB(&dob),
	         NULL);

Pros:

1) you don't have check argument types in docs all the time
2) can't make a mistake of passing the wrong type and then getting strange
   segfaults or misbehaviours.  Or having this happen only on certain
   architectures.
3) perhaps a cleaner look (cleaner look then casts)

Cons:

1) more verbose
2) not all objects use it, so if you're setting an inherited argument, you're
   back to doing it the old way for those arguments.
3) perhaps the user might use the macros in weird situations which would
   confuse the preprocessor (I dunno if this is really a con)
4) the getting of values is still not very typesafe, they only somewhat
   protect from passing non pointers, but don't check pointer types.

I've just added this and it's not absolutely finalized in gob, but I do plan
on having this or equivalent in the next gob version.  Perhaps we could use
the same thing for all the gnome objects.  One of the cons for gnome objects
would be that this would have to be done by hand, so more work (gob does this
automatically so you don't write any more code)

One other way to get more type safety is to define a static function (each
include is included only once, so it's ok for it to be static and that allows
for the compiler to optimize it away in a nicer way) for each argument such
as

static char *__my_person_set_name(char *arg) { return arg; }
static char **__my_person_get_name(char **arg) { return arg; }

#define MY_PERSON_ARG_NAME(arg)    	"name",__my_person_set_name(arg)
#define MY_PERSON_GET_ARG_NAME(arg)	"name",__my_person_get_name(arg)

This would be even harder to write by hand.  Though it may just be the scheme
I will use for gob, unless it proves too problematic.

George



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]