Boost logo

Boost :

Subject: Re: [boost] JNI library
From: Felipe Magno de Almeida (felipe.m.almeida_at_[hidden])
Date: 2012-06-17 16:22:34


On Sun, Jun 17, 2012 at 4:50 PM, Dave Abrahams <dave_at_[hidden]> wrote:
>
> on Sat Jun 16 2012, Felipe Magno de Almeida <felipe.m.almeida-AT-gmail.com> wrote:
>
>> I'm implementing the features as I need it, so it is very incomplete.
>> But it is possible to register a class like this:
>>
>> javabind::class_ component_class = env.find_class("java/awt/Component");
>> javabind::register_class
>>   (
>>     javabind::reg::class_<awt::component>(component_class)
>>     .constructor(boost::bind(boost::value_factory<awt::component>(), _1, _2
>>                              , jvm))
>>     .def<javabind::int_(awt::component const&)>
>>     ("nativeGetWidth", boost::bind(&awt::component::width, _1))
>>     .def("nativeGetHeight", &awt::component::height)
>>     .def("nativeSetX", &awt::component::set_x)
>>     .def("nativeSetY", &awt::component::set_y)
>>     .def("nativeSetWidth", &awt::component::set_width)
>>     .def("nativeSetHeight", &awt::component::set_height)
>>     .def("nativeGetX", &awt::component::get_x)
>>     .def("nativeGetY", &awt::component::get_y)
>>     .def("nativeSetVisible", &awt::component::set_visible)
>>     .def("nativeIsVisible", &awt::component::is_visible)
>>     .def("nativeSetPreferredSize", &awt::component::set_preferred_size)
>>     .def("nativeSetDelay", &awt::component::set_delay)
>>     .def("nativeGetPreferredSize", &awt::component::get_preferred_size
>>          , "java/awt/Dimension")
>>     .def("nativeSetFocus", &awt::component::set_focus)
>>   );
>>
>> And to call a method like this:
>>
>> javabind::method<void(javabind::object)> initxlet = jtv_xlet_class.method
>>   <void(javabind::object)>("initXlet", "javax/tv/xlet/XletContext");
>> initxlet(user_xlet, xlet_context);
>>
>> Any comments are appreciated,
>
> 1. Last time I looked, it was impossible to do this without a textual
>   'C' code generation layer.  I don't remember enough about the details
>   to describe the reasons, but I'd be interested to know how you get
>   around this if you recognize the limitation to which I'm referring.

The code I've pasted doesn't actually tells the whole story, in this case
there is also a .java file which implements the Java class. This class
file could be generated by the javabind library, but I thought it would
be overkill for what I needed and might actually make the loading
time longer, since it would have to be generated. I think most of this
generation could be done at compile-time, but I didn't pursue this.
As is implemented now, for each class registered there is a .java file
which loaded automatically in the classpath. This file is like this:

--
package java.awt;
public abstract class Component implements ImageObserver, Serializable
{
    private static long bootstrap;
    private long peer;
    private native void nativeInit(long bootstrap);
    protected Component()
    {
        nativeInit(bootstrap);
        assert(peer != 0);
    }
    private native boolean nativeIsVisible(long peer);
    public boolean isVisible()
    {
        return nativeIsVisible(peer);
    }
    [... other member functions ..]
}
This is tedious, and I would like to automate this,  but it is not a must-have
feature for me. The nativeInit function is implicit in register_class in the C++
side, and if it doesn't exist or doesn't have the correct signature, a exception
is thrown.
The mechanism here is that register_class sets bootstrap field with a
"virtual table" for C++'s functions and nativeInit. Then when nativeInit
is called a 'peer class' (the C++ class) is constructed in peer together
with other information about bases and a pointer to the class
'virtual table'. When every function is called the peer field is passed
to it, so that the javabind library can find its virtual table and peer class
to call.
My project must be as portable as possible, so using a generated native
function is not very attractive to me.
There are a million things that should be done better in the library
as it is, specially with regard to static typing. For now every signature
uses javabind::object and must find the 'peer class' to access it, or
make a Java call by string and etc. The JNI is very limiting though,
so for most problems I don't even have a clue on how to make it work.
> 2. I know I've been saying this for years, but we really ought to get
> the langbinding project going rather than adding new variants of
> Boost.Python for every language to which we might want to bind.
That would be good. But I surely wouldn't have the resources to help
besides the Java and Lua specifics parts.
> --
> Dave Abrahams
> BoostPro Computing
> http://www.boostpro.com
Regards,
--
Felipe Magno de Almeida

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk