From: Steve R. <sm...@su...> - 2006-11-23 23:32:18
|
Howdy, I've been looking at the JNI code produced by SWIG 1.3.29 when wrapping functions that take a char* or const char* parameter. The result doesn't look safe to me. Here's the interface file: %module test %inline{ void func1( const char* x ) {}; void func2( char* x ) {}; } Running "swig -java" produces the following code in the "_wrap.c" file =20 for func1(). JNIEXPORT void JNICALL Java_testJNI_func1(JNIEnv *jenv, jclass jcls, =20 jstring jarg1) { char *arg1 =3D (char *) 0 ; (void)jenv; (void)jcls; arg1 =3D 0; if (jarg1) { arg1 =3D (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); if (!arg1) return ; } func1((char const *)arg1); if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, arg1); } Why is arg1 a char* rather than const char*? It's a bit odd to see casting away const from the GetStringUTFChars() call, and then casting back to const to call func1(). I was alarmed at first to see that there's no exception thrown here if GetStringUTFChars() returns NULL. The JNI specifications document http://java.sun.com/j2se/1.5.0/docs/guide/jni/spec/functions.html#wp17265 simply says it returns "NULL if the operation fails". However, the older "JNI Programmer's Guide and Specification" http://java.sun.com/docs/books/jni/html/objtypes.html#4001 says that an exception is thrown. Presumably we can trust the older spec? Here's what func2() becomes. JNIEXPORT void JNICALL Java_testJNI_func2(JNIEnv *jenv, jclass jcls, =20 jstring jarg1) { char *arg1 =3D (char *) 0 ; (void)jenv; (void)jcls; arg1 =3D 0; if (jarg1) { arg1 =3D (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0); if (!arg1) return ; } func2(arg1); if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, arg1); } What alarms me about this is that func2() could try to mutate the string, which is presumably a very bad idea. Shouldn't the default typemaps be making a copy of the string in order to pass a non-const pointer to func2() rather than casting away constness and praying? Any insight appreciated. -Steve |