[Java-gnome-developer] Another possible change or two to the calling conventions?
Brought to you by:
afcowie
|
From: Dan B. <da...@mi...> - 2000-11-05 20:34:01
|
I was looking through the generated C code and noticed, wit respect to my
recent patch on return types, that there's a similar issue with how
enumerated types are passed as arguments. Although I think the code as
written does execute correctly (assuming 32 bit pointers), it involves slow
JNI calls and questionable casts, so I'd be in favor of rewriting it (which
I'd be happy to do).
Here's an example of the problem, looking at GtkBox.setChildPacking.
The Java code says this:
native public void setChildPacking(GtkWidget child, boolean expand,
boolean fill, int padding, GtkPackType pack_type);
The C signature is this:
JNIEXPORT void JNICALL Java_gtk_GtkBox_setChildPacking (JNIEnv * env,
jobject obj, jobject j_child, jboolean j_expand, jboolean j_fill, jint
j_padding, /* GtkPackType */ jint j_pack_type)
Note the last argument. Java is passing a pointer (object reference), but
the C function is accepting a 32-bit int instead (hence the problem with
non-32-bit-pointer architectures). Then in the C code, the jint is
(implicitly) cast back to a jobject to extract out the "value_" instance
variable:
jfieldID fid_arg4;
jclass cls_arg4;
jint _arg4;
[...]
cls_arg4 = (*env)->GetObjectClass(env, j_pack_type);
fid_arg4 = (*env)->GetFieldID(env, cls_arg4, "value_", "I");
_arg4 = (*env)->GetIntField(env, j_pack_type, fid_arg4);
JNI is notoriously slow, so I wouldn't recommend doing this. Rather, I'd
do the thing I did with return values, but in the other direction. The
Java code would look like this:
public void setChildPacking(GtkWidget child, boolean expand,
boolean fill, int padding, GtkPackType pack_type) {
setChildPacking0(child, expand, fill, padding, pack_type.getValue());
}
native public void setChildPacking0(GtkWidget child, boolean expand,
boolean fill, int padding, int pack_type);
The C code in question would just be this:
JNIEXPORT void JNICALL Java_gtk_GtkBox_setChildPacking (JNIEnv * env,
jobject obj, jobject j_child, jboolean j_expand, jboolean j_fill,
jint j_padding, /* GtkPackType */ jint j_pack_type) {
[...]
GtkPackType _arg4;
[...]
_arg4 = (GtkPackType) j_pack_type;
How does this sound?
Also, again for JNI avoidance reasons, it might be advisable to do the
jobject->nativepeer argument conversion in a different way than is
currently done. Concrete suggestions: Cache the JNI fieldID object
per-class so that instance methods can grab the nativepeer out of "this"
with only one JNI call (instead of 3). And pass nativepeer values directly
as parameters, unwrapping them inside Java in the same way as I propose for
enumerated types, above.
-dan
|