# HG changeset patch # User Ernst Reissner # Date 1470244259 25200 # Node ID f094186125d3b887f7d8b167f528193493764e8a # Parent 2dcabdf6d08886057f0eda634b74325be31c2dec Only convert specific Java numeric objects to double for Matlab compatibility (bug #48013) * ov-java.cc (is_auto_convertible_number): New function to test for numeric object type. (box): Use it to determine whether to return object's doubleValue. Add doxygen documentation. diff -r 2dcabdf6d088 -r f094186125d3 libinterp/octave-value/ov-java.cc --- a/libinterp/octave-value/ov-java.cc Wed Aug 03 10:06:40 2016 -0700 +++ b/libinterp/octave-value/ov-java.cc Wed Aug 03 10:10:59 2016 -0700 @@ -1075,6 +1075,59 @@ #define TO_JAVA(obj) dynamic_cast ((obj).internal_rep ()) +//! Return whether @c jobj shall be automatically converted to an Octave +//! numeric value. +//! +//! If @c jobj is an instance of any of the numeric wrapper classes @c Byte, +//! @c Integer, @c Long, @c Short, @c Float, or @c Double, then it will be +//! converted using the @c java.lang.Number.doubleValue() method. +//! +//! @param jobj Java object being returned to Octave +//! @return @c true if @c jobj shall be converted into a numeric value +//! automatically, @c false otherwise +static bool +is_auto_convertible_number (JNIEnv *jni_env, jobject jobj) +{ + jclass_ref cls (jni_env); + cls = jni_env->FindClass ("java/lang/Double"); + if (jni_env->IsInstanceOf (jobj, cls)) + return true; + cls = jni_env->FindClass ("java/lang/Float"); + if (jni_env->IsInstanceOf (jobj, cls)) + return true; + cls = jni_env->FindClass ("java/lang/Byte"); + if (jni_env->IsInstanceOf (jobj, cls)) + return true; + cls = jni_env->FindClass ("java/lang/Short"); + if (jni_env->IsInstanceOf (jobj, cls)) + return true; + cls = jni_env->FindClass ("java/lang/Integer"); + if (jni_env->IsInstanceOf (jobj, cls)) + return true; + cls = jni_env->FindClass ("java/lang/Long"); + if (jni_env->IsInstanceOf (jobj, cls)) + return true; + + return false; +} + +//! Convert the Java object pointed to by @c jobj_arg with class @c jcls_arg +//! to an Octave value. +//! +//! @param jni_env JNI environment pointer +//! @param jobj_arg pointer to a Java object +//! @param jcls_arg optional pointer to the Java class of @c jobj_arg +//! @return +//! @arg numeric value as a @c double if @c jobj_arg is of type @c Byte, +//! @c Short, @c Integer, @c Long, @c Float or @c Double +//! @arg logical value if @c jobj_arg is of type @c Boolean +//! @arg string value if @c jobj_arg is of type @c Character or @c String +//! @arg Octave array of numeric, logical, or char type if @c jobj_arg is +//! a Java array of primitive types +//! @arg Octave matrix if @c jobj_arg is of type @c org.octave.Matrix and +//! #Vjava_matrix_autoconversion is enabled +//! @arg Octave object if @c jobj_arg is of type @c org.octave.OctaveReference +//! @arg @c octave_java object wrapping the Java object otherwise static octave_value box (JNIEnv *jni_env, void *jobj_arg, void *jcls_arg) { @@ -1090,10 +1143,12 @@ while (retval.is_undefined ()) { - // Convert a scalar of any numeric class (byte, short, integer, long, - // float, double) to a double value. Matlab does the same thing. + // Convert a scalar of any numeric class wrapping a primitive class + // (byte, short, integer, long, float, double) to a double value. + // Test whether java.lang.Number before testing for each type. cls = jni_env->FindClass ("java/lang/Number"); - if (jni_env->IsInstanceOf (jobj, cls)) + if (jni_env->IsInstanceOf (jobj, cls) + && is_auto_convertible_number (jni_env, jobj)) { jmethodID m = jni_env->GetMethodID (cls, "doubleValue", "()D"); retval = jni_env->CallDoubleMethod (jobj, m);