void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, NativeType* paramTypes, FFIStorage* paramStorage, void** ffiValues, VALUE* callbackParameters, int callbackCount, VALUE enums) { VALUE callbackProc = Qnil; FFIStorage* param = ¶mStorage[0]; int i, argidx, cbidx, argCount; if (paramCount != -1 && paramCount != argc) { if (argc == (paramCount - 1) && callbackCount == 1 && rb_block_given_p()) { callbackProc = rb_block_proc(); } else { rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, paramCount); } } argCount = paramCount != -1 ? paramCount : argc; for (i = 0, argidx = 0, cbidx = 0; i < argCount; ++i) { int type = argidx < argc ? TYPE(argv[argidx]) : T_NONE; ffiValues[i] = param; switch (paramTypes[i]) { case NATIVE_INT8: param->s8 = getSignedInt(argv[argidx++], type, -128, 127, "char", Qnil); ADJ(param, INT8); break; case NATIVE_INT16: param->s16 = getSignedInt(argv[argidx++], type, -0x8000, 0x7fff, "short", Qnil); ADJ(param, INT16); break; case NATIVE_INT32: case NATIVE_ENUM: param->s32 = getSignedInt(argv[argidx++], type, -0x80000000, 0x7fffffff, "int", enums); ADJ(param, INT32); break; case NATIVE_BOOL: if (type != T_TRUE && type != T_FALSE) { rb_raise(rb_eTypeError, "wrong argument type (expected a boolean parameter)"); } param->s8 = argv[argidx++] == Qtrue; ADJ(param, INT8); break; case NATIVE_UINT8: param->u8 = getUnsignedInt(argv[argidx++], type, 0xff, "unsigned char"); ADJ(param, INT8); break; case NATIVE_UINT16: param->u16 = getUnsignedInt(argv[argidx++], type, 0xffff, "unsigned short"); ADJ(param, INT16); break; case NATIVE_UINT32: /* Special handling/checking for unsigned 32 bit integers */ param->u32 = getUnsignedInt32(argv[argidx++], type); ADJ(param, INT32); break; case NATIVE_INT64: if (type != T_FIXNUM && type != T_BIGNUM) { rb_raise(rb_eTypeError, "Expected an Integer parameter"); } param->i64 = NUM2LL(argv[argidx]); ADJ(param, INT64); ++argidx; break; case NATIVE_UINT64: if (type != T_FIXNUM && type != T_BIGNUM) { rb_raise(rb_eTypeError, "Expected an Integer parameter"); } param->u64 = NUM2ULL(argv[argidx]); ADJ(param, INT64); ++argidx; break; case NATIVE_LONG: *(ffi_sarg *) param = NUM2LONG(argv[argidx]); ADJ(param, LONG); ++argidx; break; case NATIVE_ULONG: *(ffi_arg *) param = NUM2ULONG(argv[argidx]); ADJ(param, LONG); ++argidx; break; case NATIVE_FLOAT32: if (type != T_FLOAT && type != T_FIXNUM) { rb_raise(rb_eTypeError, "Expected a Float parameter"); } param->f32 = (float) NUM2DBL(argv[argidx]); ADJ(param, FLOAT32); ++argidx; break; case NATIVE_FLOAT64: if (type != T_FLOAT && type != T_FIXNUM) { rb_raise(rb_eTypeError, "Expected a Float parameter"); } param->f64 = NUM2DBL(argv[argidx]); ADJ(param, FLOAT64); ++argidx; break; case NATIVE_STRING: param->ptr = getString(argv[argidx++], type); ADJ(param, ADDRESS); break; case NATIVE_POINTER: case NATIVE_BUFFER_IN: case NATIVE_BUFFER_OUT: case NATIVE_BUFFER_INOUT: param->ptr = getPointer(argv[argidx++], type); ADJ(param, ADDRESS); break; case NATIVE_FUNCTION: case NATIVE_CALLBACK: if (callbackProc != Qnil) { param->ptr = callback_param(callbackProc, callbackParameters[cbidx++]); } else { param->ptr = callback_param(argv[argidx], callbackParameters[cbidx++]); ++argidx; } ADJ(param, ADDRESS); break; case NATIVE_STRUCT: ffiValues[i] = getPointer(argv[argidx++], type); break; default: rb_raise(rb_eArgError, "Invalid parameter type: %d", paramTypes[i]); } } }
void rbffi_SetupCallParams(int argc, VALUE* argv, int paramCount, Type** paramTypes, FFIStorage* paramStorage, void** ffiValues, VALUE* callbackParameters, int callbackCount, VALUE enums) { VALUE callbackProc = Qnil; FFIStorage* param = ¶mStorage[0]; int i, argidx, cbidx, argCount; if (unlikely(paramCount != -1 && paramCount != argc)) { if (argc == (paramCount - 1) && callbackCount == 1 && rb_block_given_p()) { callbackProc = rb_block_proc(); } else { rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", argc, paramCount); } } argCount = paramCount != -1 ? paramCount : argc; for (i = 0, argidx = 0, cbidx = 0; i < argCount; ++i) { Type* paramType = paramTypes[i]; int type; if (unlikely(paramType->nativeType == NATIVE_MAPPED)) { VALUE values[] = { argv[argidx], Qnil }; argv[argidx] = rb_funcall2(((MappedType *) paramType)->rbConverter, id_to_native, 2, values); paramType = ((MappedType *) paramType)->type; } type = argidx < argc ? TYPE(argv[argidx]) : T_NONE; ffiValues[i] = param; switch (paramType->nativeType) { case NATIVE_INT8: param->s8 = NUM2INT(argv[argidx]); ++argidx; ADJ(param, INT8); break; case NATIVE_INT16: param->s16 = NUM2INT(argv[argidx]); ++argidx; ADJ(param, INT16); break; case NATIVE_INT32: if (unlikely(type == T_SYMBOL && enums != Qnil)) { VALUE value = rb_funcall(enums, id_map_symbol, 1, argv[argidx]); param->s32 = NUM2INT(value); } else { param->s32 = NUM2INT(argv[argidx]); } ++argidx; ADJ(param, INT32); break; case NATIVE_BOOL: if (type != T_TRUE && type != T_FALSE) { rb_raise(rb_eTypeError, "wrong argument type (expected a boolean parameter)"); } param->s8 = argv[argidx++] == Qtrue; ADJ(param, INT8); break; case NATIVE_UINT8: param->u8 = NUM2UINT(argv[argidx]); ADJ(param, INT8); ++argidx; break; case NATIVE_UINT16: param->u16 = NUM2UINT(argv[argidx]); ADJ(param, INT16); ++argidx; break; case NATIVE_UINT32: param->u32 = NUM2UINT(argv[argidx]); ADJ(param, INT32); ++argidx; break; case NATIVE_INT64: param->i64 = NUM2LL(argv[argidx]); ADJ(param, INT64); ++argidx; break; case NATIVE_UINT64: param->u64 = NUM2ULL(argv[argidx]); ADJ(param, INT64); ++argidx; break; case NATIVE_LONG: *(ffi_sarg *) param = NUM2LONG(argv[argidx]); ADJ(param, LONG); ++argidx; break; case NATIVE_ULONG: *(ffi_arg *) param = NUM2ULONG(argv[argidx]); ADJ(param, LONG); ++argidx; break; case NATIVE_FLOAT32: param->f32 = (float) NUM2DBL(argv[argidx]); ADJ(param, FLOAT32); ++argidx; break; case NATIVE_FLOAT64: param->f64 = NUM2DBL(argv[argidx]); ADJ(param, FLOAT64); ++argidx; break; case NATIVE_LONGDOUBLE: param->ld = rbffi_num2longdouble(argv[argidx]); ADJ(param, LONGDOUBLE); ++argidx; break; case NATIVE_STRING: if (type == T_NIL) { param->ptr = NULL; } else { if (rb_safe_level() >= 1 && OBJ_TAINTED(argv[argidx])) { rb_raise(rb_eSecurityError, "Unsafe string parameter"); } param->ptr = StringValueCStr(argv[argidx]); } ADJ(param, ADDRESS); ++argidx; break; case NATIVE_POINTER: case NATIVE_BUFFER_IN: case NATIVE_BUFFER_OUT: case NATIVE_BUFFER_INOUT: param->ptr = getPointer(argv[argidx++], type); ADJ(param, ADDRESS); break; case NATIVE_FUNCTION: case NATIVE_CALLBACK: if (callbackProc != Qnil) { param->ptr = callback_param(callbackProc, callbackParameters[cbidx++]); } else { param->ptr = callback_param(argv[argidx], callbackParameters[cbidx++]); ++argidx; } ADJ(param, ADDRESS); break; case NATIVE_STRUCT: ffiValues[i] = getPointer(argv[argidx++], type); break; default: rb_raise(rb_eArgError, "Invalid parameter type: %d", paramType->nativeType); } } }