From: William F. <wsf...@us...> - 2006-03-04 23:41:09
|
Update of /cvsroot/swig/SWIG/Doc/Manual In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv6127/Doc/Manual Modified Files: Java.html Log Message: Add notes about strict aliasing rules Add section on non-primitive types type mapping Index: Java.html =================================================================== RCS file: /cvsroot/swig/SWIG/Doc/Manual/Java.html,v retrieving revision 1.59 retrieving revision 1.60 diff -C2 -d -r1.59 -r1.60 *** Java.html 11 Feb 2006 18:56:30 -0000 1.59 --- Java.html 4 Mar 2006 23:41:02 -0000 1.60 *************** *** 102,105 **** --- 102,106 ---- <ul> <li><a href="#default_primitive_type_mappings">Default primitive type mappings</a> + <li><a href="#Java_default_non_primitive_typemaps">Default typemaps for non-primitive types</a> <li><a href="#jvm64">Sixty four bit JVMs</a> <li><a href="#what_is_typemap">What is a typemap?</a> *************** *** 318,321 **** --- 319,328 ---- <p> + <b>Important</b> <br> + If you are going to use optimisations turned on with gcc (for example -O2), ensure you also compile with -fno-strict-aliasing. The GCC optimisations have become + more aggressive from gcc-4.0 onwards and will result in code that fails with strict aliasing optimisations turned on. See the <a href="#typemaps_c_to_java_types">C/C++ to Java typemaps</a> section for more details. + </p> + + <p> The name of the shared library output file is important. If the name of your SWIG module is "<tt>example</tt>", the name of the corresponding shared library file should be "<tt>libexample.so</tt>" (or equivalent depending on your machine, see <a href="#dynamic_linking_problems">Dynamic linking problems</a> for more information). *************** *** 4155,4159 **** </p> ! <H3><a name="jvm64"></a>20.8.2 Sixty four bit JVMs</H3> --- 4162,4182 ---- </p> ! ! <H3><a name="Java_default_non_primitive_typemaps"></a>20.8.2 Default typemaps for non-primitive types</H3> ! ! ! <p> ! The previous section covered the primitive type mappings. ! Non-primitive types such as classes and structs are mapped using pointers on the C/C++ side and storing the pointer into a Java <tt>long</tt> variable which is held by ! the proxy class or type wrapper class. This applies whether the type is marshalled as a pointer, by reference or by value. ! It also applies for any unknown/incomplete types which use type wrapper classes. ! </p> ! ! <p> ! So in summary, the C/C++ pointer to non-primitive types is cast into the 64 bit Java <tt>long</tt> type and therefore the JNI type is a <tt>jlong</tt>. ! The Java type is either the proxy class or type wrapper class. ! </p> ! ! <H3><a name="jvm64"></a>20.8.3 Sixty four bit JVMs</H3> *************** *** 4168,4172 **** ! <H3><a name="what_is_typemap"></a>20.8.3 What is a typemap?</H3> --- 4191,4195 ---- ! <H3><a name="what_is_typemap"></a>20.8.4 What is a typemap?</H3> *************** *** 4291,4295 **** </div> ! <H3><a name="typemaps_c_to_java_types"></a>20.8.4 Typemaps for mapping C/C++ types to Java types</H3> --- 4314,4318 ---- </div> ! <H3><a name="typemaps_c_to_java_types"></a>20.8.5 Typemaps for mapping C/C++ types to Java types</H3> *************** *** 4382,4388 **** <p> The default code generated by SWIG for the Java module comes from the typemaps in the "<tt>java.swg</tt>" library file which implements the ! <a href="#default_primitive_type_mappings">Default primitive type mappings</a> ! covered earlier. There are other type mapping typemaps in the Java library. These are listed below: --- 4405,4475 ---- <p> + Note that the "in" typemap marshals the JNI type held in the "jni" typemap to the real C/C++ type and for the opposite direction, + the "out" typemap marshals the real C/C++ type to the JNI type held in the "jni" typemap. + For <a href="#Java_default_non_primitive_typemaps">non-primitive types</a> + the "in" and "out" typemaps are responsible for casting between the C/C++ pointer and the 64 bit <tt>jlong</tt> type. + There is no portable way to cast a pointer into a 64 bit integer type and the approach taken by SWIG is mostly portable, but breaks C/C++ aliasing rules. + In summary, these rules state that a pointer to any type must never be dereferenced by a pointer to any other incompatible type. + The following code snippet might aid in understand aliasing rules better: + </p> + + <div class="code"><pre> + short a; + short* pa = 0; + int i = 0x1234; + + a = (short)i; /* okay */ + a = *(short*)&i; /* breaks aliasing rules */ + </pre></div> + + <p> + An email posting, <a href="http://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html">Aliasing, pointer casts and gcc 3.3</a> elaborates further on the subject. + In SWIG, the "in" and "out" typemaps for pointers are typically + </p> + + <div class="code"><pre> + %typemap(in) struct Foo * %{ + $1 = *(struct Foo **)&$input; /* cast jlong into C ptr */ + %} + %typemap(out) struct Bar * %{ + *(struct Bar **)&$result = $1; /* cast C ptr into jlong */ + %} + struct Bar {...}; + struct Foo {...}; + struct Bar * FooBar(struct Foo *f); + </pre></div> + + <p> + resulting in the following code which breaks the aliasing rules: + </p> + + <div class="code"><pre> + JNIEXPORT jlong JNICALL Java_exampleJNI_FooBar(JNIEnv *jenv, jclass jcls, jlong jarg1) { + jlong jresult = 0 ; + struct Foo *arg1 = (struct Foo *) 0 ; + struct Bar *result = 0 ; + + (void)jenv; + (void)jcls; + + arg1 = *(struct Foo **)&jarg1; /* cast jlong into C ptr */ + + result = (struct Bar *)FooBar(arg1); + + *(struct Bar **)&jresult = result; /* cast C ptr into jlong */ + + return jresult; + } + </pre></div> + + <p> + If you are using gcc as your C compiler, you might get a "dereferencing type-punned pointer will break strict-aliasing rules" warning about this. + Please see <a href="#compiling_dynamic">Compiling a dynamic module</a> to avoid runtime problems with these strict aliasing rules. + </p> + + <p> The default code generated by SWIG for the Java module comes from the typemaps in the "<tt>java.swg</tt>" library file which implements the ! <a href="#default_primitive_type_mappings">Default primitive type mappings</a> and ! <a href="#Java_default_non_primitive_typemaps">Default typemaps for non-primitive types</a> covered earlier. There are other type mapping typemaps in the Java library. These are listed below: *************** *** 4481,4485 **** </table> ! <H3><a name="typemap_attributes"></a>20.8.5 Java typemap attributes</H3> --- 4568,4572 ---- </table> ! <H3><a name="typemap_attributes"></a>20.8.6 Java typemap attributes</H3> *************** *** 4511,4515 **** </p> ! <H3><a name="special_variables"></a>20.8.6 Java special variables</H3> --- 4598,4602 ---- </p> ! <H3><a name="special_variables"></a>20.8.7 Java special variables</H3> *************** *** 4651,4655 **** </p> ! <H3><a name="typemaps_for_c_and_c++"></a>20.8.7 Typemaps for both C and C++ compilation</H3> --- 4738,4742 ---- </p> ! <H3><a name="typemaps_for_c_and_c++"></a>20.8.8 Typemaps for both C and C++ compilation</H3> *************** *** 4688,4692 **** ! <H3><a name="java_code_typemaps"></a>20.8.8 Java code typemaps</H3> --- 4775,4779 ---- ! <H3><a name="java_code_typemaps"></a>20.8.9 Java code typemaps</H3> *************** *** 4878,4882 **** </p> ! <H3><a name="java_directors_typemaps"></a>20.8.9 Director specific typemaps</H3> --- 4965,4969 ---- </p> ! <H3><a name="java_directors_typemaps"></a>20.8.10 Director specific typemaps</H3> *************** *** 5685,5689 **** jlong cPtr = jenv->GetLongField($input, fid); MyDouble *pMyDouble = NULL; ! *(MyDouble **)(void *)&pMyDouble = *(MyDouble **)(void *)&cPtr; $1 = &pMyDouble->value; } --- 5772,5776 ---- jlong cPtr = jenv->GetLongField($input, fid); MyDouble *pMyDouble = NULL; ! *(MyDouble **)&pMyDouble = *(MyDouble **)&cPtr; $1 = &pMyDouble->value; } *************** *** 5850,5854 **** %typemap(out) Vehicle * { Ambulance *downcast = dynamic_cast<Ambulance *>($1); ! *(Ambulance **)(void *)&$result = downcast; } --- 5937,5941 ---- %typemap(out) Vehicle * { Ambulance *downcast = dynamic_cast<Ambulance *>($1); ! *(Ambulance **)&$result = downcast; } *************** *** 5918,5922 **** if (mid) { jlong cptr = 0; ! *(Ambulance **)(void *)&cptr = ambulance; $result = jenv->NewObject(clazz, mid, cptr, false); } --- 6005,6009 ---- if (mid) { jlong cptr = 0; ! *(Ambulance **)&cptr = ambulance; $result = jenv->NewObject(clazz, mid, cptr, false); } *************** *** 5929,5933 **** if (mid) { jlong cptr = 0; ! *(FireEngine **)(void *)&cptr = fireengine; $result = jenv->NewObject(clazz, mid, cptr, false); } --- 6016,6020 ---- if (mid) { jlong cptr = 0; ! *(FireEngine **)&cptr = fireengine; $result = jenv->NewObject(clazz, mid, cptr, false); } *************** *** 6157,6161 **** jfieldID fid = (*jenv)->GetFieldID(jenv, clazz, "swigCPtr", "J"); jlong cPtr = 0; ! *(Butler **)(void *)&cPtr = *$1; (*jenv)->SetLongField(jenv, $input, fid, cPtr); } --- 6244,6248 ---- jfieldID fid = (*jenv)->GetFieldID(jenv, clazz, "swigCPtr", "J"); jlong cPtr = 0; ! *(Butler **)&cPtr = *$1; (*jenv)->SetLongField(jenv, $input, fid, cPtr); } |