Re: Java support in GTK/Gnome



Tim Janik <timj@gtk.org> writes:
> i feel some more thoughtfull
> discussion from both parts needs to happen before we come up with a good
> solution. if you could forward this email, that'd be apprechiated.

That was my hope with the document.  As should be clear, my expertise is
in Java, not Gtk, so I hope Gtk/Gnome developers would use my ideas as a
starting point (as Oskar has).  (Btw:  I have discussed these idea with
Miguel, and he seems to be quite favorable.  He suggested the idea of
merging the Gtk and Java objects using CNI, but said the idea had met
opposition in the past.  I hope my "embedding" version of the idea
will have less opossition.)

> on the signal part, dealing with interfaces ala:
> 
> public ButtonClickedListener
> {
>   public void clicked ();
> }
> public class Button extends Bin
> {
>   ...
>   public native void addClickedListener(ButtonClickedListener listener);
>   public native void removeClickedListener(ButtonClickedListener listener);
> }
> ...
> will become quite cumbersome since you have the additonal overhead
> of add<SIGNAL>Listener remove<SIGNAL>Listener for ever signal on all
> objects,

I don't understand this point.  You don't get the "additonal overhead"
on "all objects".  You get appropriate methods defined in appropriate
classes.  There is no per-object overhead beyond that needed by the
existing gtk_signal_connect mechanism.

> and you don't support dynamically adding signals to existing
> classes this way.

True, but I'm not saying this is the *only* way to add signals - only
the one that would be recommended.  I think the extra type safety is 
good.

> moving to something that'd allow button.connect ("clicked", listener);
> seems far more appealing.

That would still be possible.  However, invoke a addClickedListener
method is more natural to Java programmers (it is the standard way
events are handled in Java), so I think people would prefer it,
especially since you also get compile-time type checking.

> though, then he writes (and that's the idea you seem to consider most
> appealing):
> 
> | However, there is a trick we can use, inspired by C++ multiple inheritance:
> | We embed the Gtk object in a Java Object.
> [...]
> | Note that a Gtk object has no fields that can be accessed from Java. All
> | fields have to be accessed using methods that are written in
> | native (C or C++) code. 
> [...]
> | When we create a Gtk instance, we now we actually want to do is create te
> | Java wrapper instance. For example, we want gtk_button_new() to be
> | equivalent to:
> |  (GtkWidget*) ((char*) new gnu::gtk::Button() + JAVA_OFFSET)
> 
> which does add the extra memory overhead to each GObject unconditionally.

Yes, but only a few words:  The Java Object header.  Let us say that is
two words.  (It depends on which implementation tricks/tradeoffs you use.)
Many malloc implementations also have a two-word-per-object overhead.
So the per-object memory overhead is implementation-dependent and hard to
quantify, but in any case it is relatively small.  It is certainly less
than the overhead you would get by using a separate Java proxy object.
Which would dominate depends on how may of your objects would need to
be accessed from Java - but this would be difficult to manage.

Let me emphasize that the Java Object header would only by added to
Gtk objects *if* the mem_alloc_callback is non-null and allocates a
Java object - i.e. only in Java/Gtk applications.

> i don't think physical object embedding will provide you with any significant
> advantages though. a much more viable alternative is probably to stick to
> your java proxy approach and use something like (also pseudo code of course ;):
> ...
> JProxy*
> gobject_get_jproxy (GObject *object)
> {
>   JProxy *jproxy = NULL;
>   if (object)
>     {
>       jproxy = g_object_get_data (object, "java-proxy");
>       if (!jproxy)
>         {
>           jproxy = jproxy_new_gobject (object);
>       
>           g_object_set_data_full (object, "java-proxy",
>                                   jproxy, jproxy_gobject_died);
>         }
>     }
>   return jproxy;
> }
> ...
> however, with keeping java object proxies and creating them on demand,
> you don't pay unecessary memory penalties per GObject,

However, the memory penalty for usin proxies is much bigger, plus
the time cost of mapping between a Java proxy and the GObject is
much bigger.  How significant these are depends on how many objects
need to access from Java.

One issue is garbage collection:  Each of the Java proxies has to be
registered as a "root", so it doesn't go away until the GObject goes
away *and* and references from Java go away.  This adds more overhead.

> also, at least at the object level, several language bindings can live
> in the same adress space, say i have an application that provides GObject's
> (not necessarily widgets) and want to provide scripting abilities for scheme
> and java scripts that freak around with my objects. with language bindings
> requiring physical embedding that's utterly impossible ;)

I agree this is a concern that argues for the proxy approach.  However,
the embedded approach does not preclude language mixing, as long as
at most one language at a time needs to do embedding.  It may also be
possible to use a hybrid approach, combining embedding and proxies,
for the rare cases where that is needed.

But even if you think proxies is better than embedding, I think it is
still worthwhile to offer embedding as an option, as long the cost to
the gtk core is minor.  since it clearly is more efficient in at least
some applications.  Adding a mem_alloc_callback hook seems to me like
a minor cost, especially since it seems like the kind of hook you want
to have available anyway.

Of course if you want to use both Scheme and Java the solution
is obvious: Use Kawa (http://www.gnu.org/software/kawa).  I should
know that Kawa is an excellent Scheme implementation - after all,
I wrote it!  (Less biased observers have agreed with me ...)
-- 
	--Per Bothner
per@bothner.com   http://www.bothner.com/~per/





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