Re: [gtk-devel-list] Re: GtkType stuff



On 31 Aug 1998, Marius Vollmer wrote:

> Tim Janik <timj@gtk.org> writes:
> 
> > > This is more of an issue for the static side of the type system.  We
> > > need to describe function signatures, and pass by reference is a
> > > useful technique that needs to be covered by these descriptions.
> > 
> > but this is independant of the existing argument system.
> 
> Yes.
>  
> > erm, this has nothing to do with the GtkArg structure. GtkArgs are
> > used for signals and the argument system. as you stated above, the
> > information is needed on linkage time and does not interfere with
> > the dynamic type stuff.  so why would you want to have information
> > like that in GtkArg?
> 
> GtkArgs are used to pass values to signal handlers.  Thus, as of now,
> signal handlers can only have signatures that are expressable with the
> current GtkArg structure.  Thus, there is no signal handler that has
> arguments with modes that are anything but "in".  Because the GtkArg
> structure can not express other modes.

hm, there at least have been some signal handlers like this, i.e. the
old GtkWindow::move_resize signal (still in the 1.0.x tree):
  gint (* move_resize) (GtkWindow *window,
                        gint      *x,
                        gint      *y,
                        gint       width,
                        gint       height);

in general, "in" arguments are always a little questionable for signal
handlers, because there is 1) no mechanism to check the returned values
for validity upon every handler invokation, and 2) it is not always clearly
defined when such modifications will take effect, i.e. does changing a
value that is passed by reference take effect if modified in an _after
handler?.

> But what when signal handlers start wanting to have outward arguments?
> Right now, the complete information about arguments is carried inside
> an array of GtkArg structures, and I find it natural to retain that.
> So I'd like to attach a `mode' indication to the passed values, just
> like now the type is attached to them.  For this run-time use of modes
> that are attached to values (dynamic modes, if you are so inclined, to
> go with dynamic types), I find the `optimization hint' interpretion be
> better suited.  Maybe we should ditch the name `mode' altogether and
> only talk about `flow hints' or something.  These flow hints would
> only take effect for composite types, values of all the other types
> are only allowed to flow `in'.

since this distinction is not clearly made in C, other than passing the values
by reference, signal handlers implemented in C only deal with either "in"
values or with "inout" values in that sense. so the required distinction
boils down to one bit of information, right?
for one thing we could, while preserving the current _GtkArg struct size,
reduce the actuall type information to 31 bits and have another one, indicating
"inout" behaviour:

struct _GtkArg
{
  guint type : 31;
  guint is_inout : 1;
  gchar *name;
    
  union {
  [...]
  } d;
};

but this seems somewhat hackish, and i'm not sure that we do need this at all,
since the destinction can already be made through the fundamental type
anyways. everything that can be reduced to a pure pointer value, i.e. all
objects and widgets, strings and boxed types, that get passed to a signal
handler, are already a matter to inout behaviour anyways.
another problem with your approach is that the current type system still
provides no means for passed-by-reference values for a bunch of the
fundamental types.
to get something like the above mentioned ::move_resize signal going, you have
to create the signal with:
    gtk_signal_new ("move_resize",
                    GTK_RUN_LAST,
                    object_class->type,
                    GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
                    gtk_window_marshal_signal_1,
                    GTK_TYPE_BOOL, 4,
                    GTK_TYPE_POINTER, GTK_TYPE_POINTER,
                    GTK_TYPE_INT, GTK_TYPE_INT);
which just provides the information "there is a pointer value", rather than
something like "here's a pointer that can be dereferenced to an int".
since the type system does not yet care about situations like this anyways,
it is needless to care about the actuall in/out mode of those arguments.
i bet, that as soon as this is sorted out in the actuall type system, you'd
get your in/out mode provided pretty much for free.

to carry the above mentioned on-bit-mode-information a bit further, what about
providing:

 /* Macros
  */
 #define GTK_TYPE_MAKE(parent_t, seqno)  (((seqno) << 8) | GTK_FUNDAMENTAL_TYPE (parent_t))
-#define GTK_FUNDAMENTAL_TYPE(type)      ((GtkFundamentalType) ((type) & 0xFF))
-#define GTK_TYPE_SEQNO(type)            ((type) > 0xFF ? (type) >> 8 : (type))
+#define GTK_FUNDAMENTAL_TYPE(type)      \
+ ((GtkFundamentalType) (((type) & GTK_REFERENCE_FLAG) ? GTK_TYPE_POINTER : (type) & 0xFF))
+#define GTK_TYPE_SEQNO(type)            \
+ (((type) & (~GTK_REFERENCE_FLAG) > 0xFF) ? ((type) & (~GTK_REFERENCE_FLAG) >> 8 : \
+   ((type) & (~GTK_REFERENCE_FLAG))
+#define GTK_REFERENCE_FLAG              (1 << 32)  
+#define GTK_REFERENCE_TYPE(type)        ((type) | GTK_REFERENCE_FLAG)
+#define GTK_IS_REFERENCE_TYPE(type)     (((type) & GTK_REFERENCE_FLAG) != 0)

with this, for the above mentioned ::move_resize signal, you'd actually do:
    gtk_signal_new ("move_resize",
                    GTK_RUN_LAST,
                    object_class->type,
                    GTK_SIGNAL_OFFSET (GtkWindowClass, move_resize),
                    gtk_window_marshal_signal_1,
                    GTK_TYPE_BOOL, 4,
                    GTK_REFERENCE_TYPE (GTK_TYPE_INT),
                    GTK_REFERENCE_TYPE (GTK_TYPE_INT),
                    GTK_TYPE_INT,
                    GTK_TYPE_INT);
thus preserving the original type information, that is passed by reference,
and additionally, get your inout mode encoded into the GtkArg structure while
preserving its current layout.

> Since there are no composite types now, no existing code needs to
> change and we don't have the problem how to implement outward flow for
> the existing types.
> 
> > also, i'd like to keep the GtkArg structure as small as possible, since
> > gui builders and eventually some langueage bindings make extensive use
> > of it.
> 
> Can we remove the `name' field?

this would break all of the GtkArg api calls. you are right in that the
argument name is not required for signal arguments, but it is of big
importance for the argument system. without the argument name, we'd not
be able to, for instance, query a certain argument value from an object
or set it via gtk_object_getv/gtk_object_setv.

> I think the most prominent user of GtkArg structures right now is the
> signal system.

nope, the signaling system does actually only need the argument values
and their type information, but GtkArgs are also used by the object
argument system, which indeed does makes extensive use of the argument names.
you should give GLE (a cvs module) a try, check it out, compile it,
and invoke a gtk program with --gtk-module=gle, then press ctl+alt+tab
in a gtk window and play a little with the widget editor. there's a
*bunch* of arguments that can be adjusted/assigned to the several widget
types, and all of them require an argument name badly ;)

>  I've shortly thought about avoiding this by putting
> some assembler magic into place that extents the va_args mechanism so
> that you can call a function with an va_list.  Along the lines of what
> libffi or ffcall provide, but more specialized.

peter wrote a few lines on why he had not taken this approach for the
signaling system in the .texi files.  i think the biggest problem with
constructing functions calls is portability. Gtk runs on a variety of
systems currently, and without getting comprehensive access to these
systems we can't adhock let the existing marshalling mechanism vanish,
in favour of a global function call constructor.
i don't know how portable libffi/ffcall are, though...

> [ Declarations in header files ]
> 
> > i'd guess that some simple rules would basically do the trick for the
> > in/out stuff, e.g. return values are always out, with char* being
> > considered as dynamically allocated by default. similar rules would apply
> > for the function arguments, e.g. "int", "float" and "char*" are considered
> > `in' parameters and "int*", "float*" and "char**" are considered `out'.
> 
> This can work to get a useful approximation to the initial definitions
> into the header files.  But I don't think we should use this magic
> routinely.
> 
> That is, as a one shot tool to save us (ok, me) a large amount of work
> up front, this would be very useful.  But I *don't* want to have a
> situation where someone innocently puts a funtion prototype into a
> header file, and then it gets magically converted into a *.defs
> definition which is wrong, without anybody ever noticing.
> 
> > (define-func gtk_widget_get_name
> >   (string (mode dynamic-alloc))
> >   ((GtkWidget *widget)))
> 
> There should be no `*' in the definition.

hm, i just saw one of your function definitions, refering to an "int *", since
you've not yet layed out the new .defs format, the asterisk was just a guess.

> > > > the results could then be adapted for some functions that need special
> > > > casing.
> > > 
> > > Hmm, too tricky, in my view.  The default should be safe.  So when you
> > > do not specifically declare a function to be fit for gtk.defs it
> > > shouldn't be included, IMO.
> > 
> > i don't think this scheme is too tricky, and it has been sufficient for
> > at least the enums ;)
> 
> Ahh, the enums!  Piece'o'cake! :-)
> 
> > i think we can get close to the matching-rate for enums with the function
> > definitions as well, if we come up with smart defaults for the .defs
> > generator.
> 
> I think the same, but I don't want to stop at being close.  I want to
> get there.

that's what i intended the comment-enclosed hints for, just like
owen did for enums.

>  You know, Windows apps aren't crappy because they run on
> Windows.  They are crappy because they are crappy.  Just not writing
> for Windows can't save you from writing crappy apps. ;-)
> 
> > > When they don't know how to do it, then their functions shouldn't be
> > > described in gtk.defs.
> 
> I want to make clear that I don't blame anyone for not knowing how to
> do it.
> 
> Well, many years ago, when it came to confessing on which side of the
> C/Pascal medal one was, I was a strong C believer.  If I would've
> known about Usenet flamewars then, you could've probably hear me say
> some very offensive things about P.  But I think I've gotten over
> this.  There is this saying that Pascal makes you beg "please, please,
> let me do this, I know what`m doing.", but it wont let you.  C makes
> you say: "I'm sorry, I didn't meant to...".  There's got to be a
> middle way.  I want to try to offer this middle way with the type
> system.

i'm not sure how you intend to make gtk's type system cure so-believed
deficiencies of the C language.
i guess, a good start at advancing gtk's type system in a usefull way,
is to solve the above mentioned pass-by-reference problem.
you'll get yor in/out problems solved by that automatically, and maybe
even some of the little stuffs that you didn't mean to do in C ;)
as far as C vs. Pascal goes, i think both of the two languages have their
place, and if you come close to a point where Pascal doesn't fit your
needs anymore you should have either choosen a different language right
from the beginning, or you've made some fundamental mistakes conceptually.
but this applies more-or-less to pretty much all languages in existance.

---
ciaoTJ



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