Today I helped Anthony debug a libgcj problem over irc. I sure
wish there were an easy way to hook an irc session up to an
already-running gdb so we could interactively share the debugger.
Anyone have a cool hack for this? Preferably one that has some sense
built into it so that not just anybody can hijack the debugger…
GDirect
I spent a little time yesterday working on an easy way to create
native methods for Java. I call it “GDirect”. The idea is pretty
simple, basically have a package that creates native method
implementations on the fly, based on declarations in your code. So,
e.g., you would write something like this:
public class example { static { // Second argument is base name of shared library. GDirect.link (example.class, "m"); } public static native double atan (double x); }
In this example, example.atan
will call the C math
library function atan
, nothing more is needed.
Issues
There are a few issues with this approach. One is pointers, but
with gcj we can just represent these with RawData
.
Another is structures, which I’m just punting on. A third issue is
type mismatch — if the Java int
and the C
int
are not the same, you need translation at runtime.
So far I’m not handling this, but it is actually pretty easy to deal
with. There are some other type-mapping issues to resolve as well,
I’ll look at those more a bit later.
Since this uses JNI under the hood, it is pretty slow. With the
upcoming binary compatibility ABI in gcj, though, we can do better
there. In some situations we can completely eliminate the need for a
runtime stub and just have direct calls to the C functions from
Java.
Opportunities
This code can be made completely portable across JVMs without much
effort. It works by creating new functions on the fly with libffi,
and it registers these functions with the JVM via the JNI
RegisterNatives
call. For gcj, we’ll have some CNI
equivalent of this in the not-too-distant future, so we’ll be able to
make GDirect both portable and more efficient when running on our
implementation.
libffi’s closure API is what makes this possible. It works on
most platforms, though not all yet. I think a similar technique could
be used to make bridges in other places, e.g. interfacing Java to
Mozilla or to OOo.
Another random idea is to make it simpler to wrap libraries that
already have an object-oriented interface. One way we could do this
would be to tell GDirect about a field which holds a native pointer.
Then we would treat non-static native methods specially, looking up
the native pointer at invocation time and passing it to the underlying
C API. Combined with a simple facility to rewrite method names when
linking, this would make it very easy to create and maintain, say, a
Gtk wrapper library. For instance, something like
gtk_window_set_type_hint
would become:
public class GtkWindow extends ... { // This would actually be in a superclass somewhere. private RawData nativeInfo; static { GDirect.link (GtkWindow.class, "gtk", "nativeInfo", GtkRewriter.getInstance ()); } public native void setTypeHint (int hint); }
Here, GtkRewriter would be a special class that would know how to
transform “GtkWindow.setTypeHint” into “gtk_window_set_type_hint”.
Be the first to leave a comment. Don’t be shy.