[Java] Function Binding Redux (long post)

John Moeller <[email protected]>
Newsgroups gmane.comp.lib.boost.langbinding
Message-ID <[email protected]>
Okay.  So I've been spending the last few weeks attempting to figure out 
how one would use a "natural" syntax to make a function call in the Java 
Langbinding, that is, if you have a Langbinding class "X" and a function 
"f" defined as a member, how can you write code such as this:

   X x = new X(...);
   ...
   SomeClass sc = x.f(y, z, 42);

The short answer seems to be "not easily."  At the very least, at the 
center of any solution needs to be some kind of function dispatcher on 
the Java side that will take in the arguments, pass them to the 
Langbinding module, and get the return.  Whether it's as simple as:

   public <ReturnValue> ReturnValue call(Object ... args) { ... }

or something involving more encapsulation, something akin to this needs 
to dispatch the function call.

So here's the solutions so far:

1.  Use the function dispatcher directly.

This is ok, but not great, and it's certainly a step away from natural. 
  It's at least not entirely procedural, because you can define a 
wrapper object and make a call on it:

   import boost.langbinding.Instance;
   ...
   Instance x = new Instance("X", arg1, arg2, arg3);
   x.call("f", arg4, arg5);

2a. Generate a Java source file where the methods wrap the function 
dispatcher.

Not entirely appealing, because it's a build-time solution, not a 
runtime solution.  But it would enable the use of "natural" syntax very 
easily.

2b. Generate the same, except directly in bytecode, and put the result 
in a class file.

Same advantages as (2a), except without the compile time, but the 
drawback that we'd have to maintain bytecode generation (probably not a 
big deal, though).

3.  Do the same as (2b), but load the class at runtime with a special 
class loader.  This is (from what I understand) the crux of Rene's idea, 
and the most initially appealing.

I've been trying to think of ways to make this work, but there are some 
major compromises:

   1.  Without wrangling class loaders at startup, it's impossible to use
       the class name in source code without it having been loaded first.
       This means that you have to load the class, then use it through
       its Class interface.  This means using reflection, which is an
       entirely procedural API.  It's pretty gross.  If the class can
       implement an interface though, (I'm referring to the Java kind of
       interface), then you could just cast it, because a class can
       implement an interface that's already been loaded by another class
       loader with no problem.

   2.  You could wrangle class loaders at startup, or some major
       milestone in your program's execution.  That is, you could come up
       with a "launcher" that set up the class loader chain, and invoke
       "main" from your main app class.  This would enable you to use
       your generated classes naturally, because the main class would be
       loaded with the special class loader in the loader chain, and all
       of its dependent classes (i.e., the rest of the program) would be
       loaded with the same loader chain.

       Unfortunately, this means that you can't have your app classes
       visible from the launcher's classpath.  You actually have to take
       steps to *prevent* the default loaders from finding your app
       classes.  This is inconvenient, and may simply be impossible for
       some users.  They may not have control over how their classes are
       started.

   3.  Hack the JVM startup so that it uses a different class loader.
       This still has the problem of accessibility, and probably the
       problem of portability, because not all JVMs may implement an app
       class loader override.

I thought of another alternative.  If we're willing to compromise on 
natural syntax, we can go one better than compromise (1) above.  I got 
this idea from looking at the Java scripting API.  In the scripting API, 
you can pass an interface class to your script object, and have it 
return an object defined in the script as an instance of the interface.

We could do something like this:

   Instance x = new Instance("X", ctorArg1, ctorArg2);
   Runnable r = x.asInterface(Runnable.class);

   new Thread(r).start();

or even:

   WrappedClass x = new WrappedClass("X");
   Runnable r = x.asInterface(Runnable.class, ctorArg1, ctorArg2);

   new Thread(r).start();

This would presumably throw an exception if there wasn't a function void 
run() that could be dispatched to.

It seems that it should be possible to generate a class that implements 
an interface on the fly (I think that implemented interfaces are just 
markers in the class data anyway).

What do you think?

-- 

John Moeller
[email protected]


-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.