static void emitFromNativeConversion( AsmBuilder builder, SkinnyMethodAdapter mv, FromNativeType fromNativeType, Class nativeClass) { // If there is a result converter, retrieve it and put on the stack FromNativeConverter fromNativeConverter = fromNativeType.getFromNativeConverter(); if (fromNativeConverter != null) { convertPrimitive( mv, nativeClass, unboxedType(fromNativeConverter.nativeType()), fromNativeType.getNativeType()); boxValue(builder, mv, fromNativeConverter.nativeType(), nativeClass); Method fromNativeMethod = getFromNativeMethod(fromNativeType, builder.getClassLoader()); getfield(mv, builder, builder.getFromNativeConverterField(fromNativeConverter)); mv.swap(); if (fromNativeType.getFromNativeContext() != null) { getfield( mv, builder, builder.getFromNativeContextField(fromNativeType.getFromNativeContext())); } else { mv.aconst_null(); } if (fromNativeMethod.getDeclaringClass().isInterface()) { mv.invokeinterface( fromNativeMethod.getDeclaringClass(), fromNativeMethod.getName(), fromNativeMethod.getReturnType(), fromNativeMethod.getParameterTypes()); } else { mv.invokevirtual( fromNativeMethod.getDeclaringClass(), fromNativeMethod.getName(), fromNativeMethod.getReturnType(), fromNativeMethod.getParameterTypes()); } if (fromNativeType.getDeclaredType().isPrimitive()) { // The actual return type is a primitive, but there was a converter for it - extract the // primitive value Class boxedType = getBoxedClass(fromNativeType.getDeclaredType()); if (!boxedType.isAssignableFrom(fromNativeMethod.getReturnType())) mv.checkcast(p(boxedType)); unboxNumber( mv, boxedType, fromNativeType.getDeclaredType(), fromNativeType.getNativeType()); } else if (!fromNativeType .getDeclaredType() .isAssignableFrom(fromNativeMethod.getReturnType())) { mv.checkcast(p(fromNativeType.getDeclaredType())); } } else if (!fromNativeType.getDeclaredType().isPrimitive()) { Class unboxedType = unboxedType(fromNativeType.getDeclaredType()); convertPrimitive(mv, nativeClass, unboxedType, fromNativeType.getNativeType()); boxValue(builder, mv, fromNativeType.getDeclaredType(), unboxedType); } }
static void emitToNativeConversion( AsmBuilder builder, SkinnyMethodAdapter mv, ToNativeType toNativeType) { ToNativeConverter parameterConverter = toNativeType.getToNativeConverter(); if (parameterConverter != null) { Method toNativeMethod = getToNativeMethod(toNativeType, builder.getClassLoader()); if (toNativeType.getDeclaredType().isPrimitive()) { boxValue( builder, mv, getBoxedClass(toNativeType.getDeclaredType()), toNativeType.getDeclaredType()); } if (!toNativeMethod.getParameterTypes()[0].isAssignableFrom( getBoxedClass(toNativeType.getDeclaredType()))) { mv.checkcast(toNativeMethod.getParameterTypes()[0]); } mv.aload(0); AsmBuilder.ObjectField toNativeConverterField = builder.getToNativeConverterField(parameterConverter); mv.getfield( builder.getClassNamePath(), toNativeConverterField.name, ci(toNativeConverterField.klass)); if (!toNativeMethod.getDeclaringClass().equals(toNativeConverterField.klass)) { mv.checkcast(toNativeMethod.getDeclaringClass()); } // Re-order so the value to be converted is on the top of the stack mv.swap(); // load context parameter (if there is one) if (toNativeType.getToNativeContext() != null) { getfield(mv, builder, builder.getToNativeContextField(toNativeType.getToNativeContext())); } else { mv.aconst_null(); } if (toNativeMethod.getDeclaringClass().isInterface()) { mv.invokeinterface( toNativeMethod.getDeclaringClass(), toNativeMethod.getName(), toNativeMethod.getReturnType(), toNativeMethod.getParameterTypes()); } else { mv.invokevirtual( toNativeMethod.getDeclaringClass(), toNativeMethod.getName(), toNativeMethod.getReturnType(), toNativeMethod.getParameterTypes()); } if (!parameterConverter.nativeType().isAssignableFrom(toNativeMethod.getReturnType())) { mv.checkcast(p(parameterConverter.nativeType())); } } }
static void unboxNumber( final SkinnyMethodAdapter mv, final Class boxedType, final Class unboxedType, final jnr.ffi.NativeType nativeType) { if (Number.class.isAssignableFrom(boxedType)) { switch (nativeType) { case SCHAR: case UCHAR: mv.invokevirtual(p(boxedType), "byteValue", "()B"); convertPrimitive(mv, byte.class, unboxedType, nativeType); break; case SSHORT: case USHORT: mv.invokevirtual(p(boxedType), "shortValue", "()S"); convertPrimitive(mv, short.class, unboxedType, nativeType); break; case SINT: case UINT: case SLONG: case ULONG: case ADDRESS: if (sizeof(nativeType) == 4) { mv.invokevirtual(p(boxedType), "intValue", "()I"); convertPrimitive(mv, int.class, unboxedType, nativeType); } else { mv.invokevirtual(p(boxedType), "longValue", "()J"); convertPrimitive(mv, long.class, unboxedType, nativeType); } break; case SLONGLONG: case ULONGLONG: mv.invokevirtual(p(boxedType), "longValue", "()J"); narrow(mv, long.class, unboxedType); break; case FLOAT: mv.invokevirtual(p(boxedType), "floatValue", "()F"); break; case DOUBLE: mv.invokevirtual(p(boxedType), "doubleValue", "()D"); break; } } else if (Boolean.class.isAssignableFrom(boxedType)) { unboxBoolean(mv, unboxedType); } else { throw new IllegalArgumentException("unsupported boxed type: " + boxedType); } }
static void unboxNumber( final SkinnyMethodAdapter mv, final Class boxedType, final Class nativeType) { if (Number.class.isAssignableFrom(boxedType)) { if (byte.class == nativeType) { mv.invokevirtual(p(boxedType), "byteValue", "()B"); } else if (short.class == nativeType) { mv.invokevirtual(p(boxedType), "shortValue", "()S"); } else if (int.class == nativeType) { mv.invokevirtual(p(boxedType), "intValue", "()I"); } else if (long.class == nativeType) { mv.invokevirtual(p(boxedType), "longValue", "()J"); } else if (float.class == nativeType) { mv.invokevirtual(p(boxedType), "floatValue", "()F"); } else if (double.class == nativeType) { mv.invokevirtual(p(boxedType), "doubleValue", "()D"); } else { throw new IllegalArgumentException("unsupported Number subclass: " + boxedType); } } else if (Boolean.class.isAssignableFrom(boxedType)) { unboxBoolean(mv, nativeType); } else { throw new IllegalArgumentException("unsupported boxed type: " + boxedType); } }
static void unboxBoolean(final SkinnyMethodAdapter mv, Class boxedType, final Class nativeType) { mv.invokevirtual(p(boxedType), "booleanValue", "()Z"); widen(mv, boolean.class, nativeType); }