[Kde-java] Re: Should we ditch support for Sun's JDK in favour of
Free Software?
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Sat Apr 17 11:32:38 CEST 2004
On Friday 16 April 2004 22:54, Tom Tromey wrote:
> >>>>> "Richard" == Richard Dale <Richard_Dale at tipitina.demon.co.uk> writes:
>
> Richard> I'm only really talking about the next version for KDE 3.3
> Richard> based on dynamic proxies. I think it just means I'll do a CNI
> Richard> version first, and then do a JNI/jdk oriented one if I've got
> Richard> time. There will only be about 20 CNI or JNI methods, so it
> Richard> will be easier to do both CNI/JNI.
>
> This sounds excellent. Can these new native methods also be
> auto-generated? That might make it even easier to support both.
No, they are the various support funtions needed to interface with the Smoke
library - a 'Smoke Adaptor'. They have no dependencies on Qt/KDE classes
apart from custom marshallers to convert from a C++ list type to ArrayLists
for instance. That code doesn't need changing for each release, and is easy
to maintain. Everything else is autogenerated as part of kdebindings
configure - both the Smoke library, and all the .java classes with the
interceptor proxies.
I did start on the interface with Proxy.invoke() to a native method a few
months ago, but it seemed unnecessarily difficult to convert from a Object[]
array to an array of jvalues, which are then pushed as C++ values onto the
'Smoke::Stack'. A lot of the code is for converting Object[] <-->
Smoke::Stack, you push things onto the Smoke::Stack to invoke a C++ method,
or you take things off the Smoke::Stack for a callback for a virtual method
override or slot invocation. I'm assuming the way CNI works will make it a
lot simpler.
Below is the code to invoke a C++ method from ruby as an example of the sort
of thing it looks like. In ruby the method_missing() method (the equivalent
of Proxy.invoke() in java), is passed an array of ruby VALUEs that are then
passed straight the MethodCall constructor, the '_sp' variable in the code
below. But in java JNI it's quite involved.
'Smoke::Index' which identifies which method to call in the Smoke runtime, is
actually as integer from 0..29000. In version 2 of the Smoke runtime it will
be a URI which will be more flexible.
-- Richard
class MethodCall : public Marshall {
int _cur;
Smoke *_smoke;
Smoke::Stack _stack;
Smoke::Index _method;
Smoke::Index *_args;
VALUE _target;
void *_current_object;
Smoke::Index _current_object_class;
VALUE *_sp;
int _items;
VALUE _retval;
bool _called;
public:
MethodCall(Smoke *smoke, Smoke::Index method, VALUE target, VALUE *sp, int
items) :
_cur(-1), _smoke(smoke), _method(method), _target(target),
_current_object(0), _sp(sp), _items(items), _called(false)
{
if (_target != Qnil) {
smokeruby_object *o = value_obj_info(_target);
if (o && o->ptr) {
_current_object = o->ptr;
_current_object_class = o->classId;
}
}
_args = _smoke->argumentList + _smoke->methods[_method].args;
_items = _smoke->methods[_method].numArgs;
_stack = new Smoke::StackItem[items + 1];
_retval = Qnil;
}
~MethodCall() {
delete[] _stack;
}
SmokeType type() {
return SmokeType(_smoke, _args[_cur]);
}
Marshall::Action action() {
return Marshall::FromVALUE;
}
Smoke::StackItem &item() {
return _stack[_cur + 1];
}
VALUE * var() {
if(_cur < 0) return &_retval;
return _sp + _cur;
}
inline const Smoke::Method &method() {
return _smoke->methods[_method];
}
void unsupported() {
if (strcmp(_smoke->className(method().classId), "QGlobalSpace") == 0) {
rb_raise(rb_eArgError, "Cannot handle '%s' as argument to %s",
type().name(),
_smoke->methodNames[method().name]);
} else {
rb_raise(rb_eArgError, "Cannot handle '%s' as argument to %s::%s",
type().name(),
_smoke->className(method().classId),
_smoke->methodNames[method().name]);
}
}
Smoke *smoke() {
return _smoke;
}
inline void callMethod() {
if(_called) return;
_called = true;
Smoke::ClassFn fn = _smoke->classes[method().classId].classFn;
void *ptr = _smoke->cast(_current_object, _current_object_class,
method().classId);
_items = -1;
(*fn)(method().method, ptr, _stack);
MethodReturnValue r(_smoke, _method, _stack, &_retval);
}
void next() {
int oldcur = _cur;
_cur++;
while(!_called && _cur < _items) {
Marshall::HandlerFn fn = getMarshallFn(type());
(*fn)(this);
_cur++;
}
callMethod();
_cur = oldcur;
}
bool cleanup() {
return true;
}
};
More information about the Kde-java
mailing list