private static IRubyObject callConversionMethod( ThreadContext context, DynamicMethod method, IRubyObject converter, String methodName, IRubyObject value) { if (method.getArity().required() == 2) { return method.call( context, converter, converter.getMetaClass(), methodName, value, context.runtime.getNil()); } else { return method.call(context, converter, converter.getMetaClass(), methodName, value); } }
private IRubyObject invokeRuby( final DynamicMethod method, final JavaProxyMethod proxyMethod, final RubyClass metaClass, final String name, final Object[] nargs) { final IRubyObject[] newArgs = new IRubyObject[nargs.length]; for (int i = nargs.length; --i >= 0; ) { newArgs[i] = JavaUtil.convertJavaToUsableRubyObject(runtime, nargs[i]); } final int arity = method.getArity().getValue(); if (arity < 0 || arity == newArgs.length) { final ThreadContext context = runtime.getCurrentContext(); return method.call(context, self, metaClass, name, newArgs); } if (proxyMethod.hasSuperImplementation()) { final ThreadContext context = runtime.getCurrentContext(); final RubyClass superClass = metaClass.getSuperClass(); return Helpers.invokeAs(context, superClass, self, name, newArgs, Block.NULL_BLOCK); } throw runtime.newArgumentError(newArgs.length, arity); }
@JRubyMethod(name = "new", meta = true) public static final IRubyObject newMappedType( ThreadContext context, IRubyObject klass, IRubyObject converter) { if (!converter.respondsTo("native_type")) { throw context.runtime.newNoMethodError( "converter needs a native_type method", "native_type", converter.getMetaClass()); } DynamicMethod toNativeMethod = converter.getMetaClass().searchMethod("to_native"); if (toNativeMethod.isUndefined()) { throw context.runtime.newNoMethodError( "converter needs a to_native method", "to_native", converter.getMetaClass()); } if (toNativeMethod.getArity().required() < 1 || toNativeMethod.getArity().required() > 2) { throw context.runtime.newArgumentError("to_native should accept one or two arguments"); } DynamicMethod fromNativeMethod = converter.getMetaClass().searchMethod("from_native"); if (fromNativeMethod.isUndefined()) { throw context.runtime.newNoMethodError( "converter needs a from_native method", "from_native", converter.getMetaClass()); } if (fromNativeMethod.getArity().required() < 1 || fromNativeMethod.getArity().required() > 2) { throw context.runtime.newArgumentError("from_native should accept one or two arguments"); } Type nativeType; try { nativeType = (Type) converter.callMethod(context, "native_type"); } catch (ClassCastException ex) { throw context.runtime.newTypeError("native_type did not return instance of FFI::Type"); } boolean isReferenceRequired; if (converter.respondsTo("reference_required?")) { isReferenceRequired = converter.callMethod(context, "reference_required?").isTrue(); } else { switch (nativeType.nativeType) { case BOOL: case CHAR: case UCHAR: case SHORT: case USHORT: case INT: case UINT: case LONG: case ULONG: case LONG_LONG: case ULONG_LONG: case FLOAT: case DOUBLE: isReferenceRequired = false; break; default: isReferenceRequired = true; break; } } return new MappedType( context.runtime, (RubyClass) klass, nativeType, converter, toNativeMethod, fromNativeMethod, isReferenceRequired); }