[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 |