Beispiel #1
0
func newTypeFromFactoryFunction(function interface{}, factoryType reflect.Type, parameters []interface{}) TypeFactory {
	if factoryType.NumOut() != 1 {
		return newInvalidType(fmt.Errorf("invalid number of return parameters: %d", factoryType.NumOut()))
	}

	kindOfGeneratedType := factoryType.Out(0).Kind()
	if kindOfGeneratedType != reflect.Interface && kindOfGeneratedType != reflect.Ptr {
		return newInvalidType(fmt.Errorf("return parameter is no interface or pointer but a %v", kindOfGeneratedType))
	}

	if factoryType.IsVariadic() {
		if factoryType.NumIn() > len(parameters) {
			return newInvalidType(fmt.Errorf("invalid number of input parameters for variadic function: got %d but expected at least %d", len(parameters), factoryType.NumIn()))
		}
	} else {
		if factoryType.NumIn() != len(parameters) {
			return newInvalidType(fmt.Errorf("invalid number of input parameters: got %d but expected %d", len(parameters), factoryType.NumIn()))
		}
	}

	t := &typeFactory{
		factory:     reflect.ValueOf(function),
		factoryType: factoryType,
	}

	var err error
	t.factoryArguments, err = buildFactoryCallArguments(factoryType, parameters)
	if err != nil {
		return newInvalidType(err)
	}

	return t
}
Beispiel #2
0
// t's Kind must be a reflect.Func.
func funcArgsFromType(t reflect.Type) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) {
	nin := t.NumIn()
	if t.IsVariadic() {
		nin--
	}
	var p *Parameter
	for i := 0; i < nin; i++ {
		p, err = parameterFromType(t.In(i))
		if err != nil {
			return
		}
		in = append(in, p)
	}
	if t.IsVariadic() {
		p, err = parameterFromType(t.In(nin).Elem())
		if err != nil {
			return
		}
		variadic = p
	}
	for i := 0; i < t.NumOut(); i++ {
		p, err = parameterFromType(t.Out(i))
		if err != nil {
			return
		}
		out = append(out, p)
	}
	return
}
Beispiel #3
0
func getInputTypeString(i int, ft reflect.Type) string {
	numInputs := ft.NumIn()
	if i == numInputs-1 && ft.IsVariadic() {
		return "..." + getTypeString(ft.In(i).Elem())
	}

	return getTypeString(ft.In(i))
}
Beispiel #4
0
// safeNumericConvert converts numeric parameter val from js to the type that the function fn expects if its safe to do so.
// This allows literals (int64) and the general js numeric form (float64) to be passed as parameters to go functions easily.
func safeNumericConvert(fn reflect.Type, i int, val interface{}) reflect.Value {
	switch val.(type) {
	default:
		// Not a supported conversion
		return reflect.ValueOf(val)
	case float64, int64:
		// What type is the func expecting?
		var ptype reflect.Type
		switch {
		case fn.IsVariadic() && fn.NumIn() <= i+1:
			// This argument is variadic so use the variadics element type.
			ptype = fn.In(fn.NumIn() - 1).Elem()
		case fn.NumIn() > i:
			ptype = fn.In(i)
		}

		if f64, ok := val.(float64); ok {
			switch ptype.Kind() {
			case reflect.Float64:
				return reflect.ValueOf(val)
			case reflect.Float32:
				if reflect.Zero(ptype).OverflowFloat(f64) {
					// Not safe to convert
					return reflect.ValueOf(val)
				}

				return reflect.ValueOf(val).Convert(ptype)
			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
				i64 := int64(f64)
				if float64(i64) != f64 {
					// Not safe to convert
					return reflect.ValueOf(val)
				}

				// The float represents an integer
				val = i64
			default:
				// Not a supported conversion
				return reflect.ValueOf(val)
			}
		}

		i64 := val.(int64)
		switch ptype.Kind() {
		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32:
			if !reflect.Zero(ptype).OverflowInt(i64) {
				return reflect.ValueOf(val).Convert(ptype)
			}
		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
			if i64 > 0 && !reflect.Zero(ptype).OverflowUint(uint64(i64)) {
				return reflect.ValueOf(val).Convert(ptype)
			}
		}
	}

	// Not a supported conversion
	return reflect.ValueOf(val)
}
Beispiel #5
0
func (r concreteRunner) extractMethodArgs(runMethodType reflect.Type, protocolVersion ProtocolVersion, args []interface{}) (methodArgs []reflect.Value, err error) {
	numberOfArgs := runMethodType.NumIn()
	numberOfReqArgs := numberOfArgs

	if runMethodType.IsVariadic() {
		numberOfReqArgs--
	}

	argsOffset := 0

	if numberOfArgs > 0 {
		firstArgType := runMethodType.In(0)

		if firstArgType.Name() == "ProtocolVersion" {
			methodArgs = append(methodArgs, reflect.ValueOf(protocolVersion))
			numberOfReqArgs--
			argsOffset++
		}
	}

	if len(args) < numberOfReqArgs {
		err = bosherr.Errorf("Not enough arguments, expected %d, got %d", numberOfReqArgs, len(args))
		return
	}

	for i, argFromPayload := range args {
		var rawArgBytes []byte
		rawArgBytes, err = json.Marshal(argFromPayload)
		if err != nil {
			err = bosherr.WrapError(err, "Marshalling action argument")
			return
		}

		argType, typeFound := r.getMethodArgType(runMethodType, i+argsOffset)
		if !typeFound {
			continue
		}

		argValuePtr := reflect.New(argType)

		err = json.Unmarshal(rawArgBytes, argValuePtr.Interface())
		if err != nil {
			err = bosherr.WrapError(err, "Unmarshalling action argument")
			return
		}

		methodArgs = append(methodArgs, reflect.Indirect(argValuePtr))
	}

	return
}
func (r JSONCaller) getMethodArgType(methodType reflect.Type, index int) (argType reflect.Type, found bool) {
	numberOfArgs := methodType.NumIn()

	switch {
	case !methodType.IsVariadic() && index >= numberOfArgs:
		return nil, false

	case methodType.IsVariadic() && index >= numberOfArgs-1:
		sliceType := methodType.In(numberOfArgs - 1)
		return sliceType.Elem(), true

	default:
		return methodType.In(index), true
	}
}
Beispiel #7
0
// Funkcja sprawdza zgodnosc typow argumentow. Jesli to konieczne konwertuje
// argumenty do typu interface{}. Jesli to potrzebne, funkcja odpowiednio
// dostosowuje args dla funkcji.
func argsMatch(ft reflect.Type, args []reflect.Value, method int) int {
	if ft.NumOut() == 0 {
		return RUN_NOT_RET
	}
	// Liczba arguemntow akceptowanych przez funkcje/metode
	num_in := ft.NumIn() - method
	// Sprawdzamy zgodnosc liczby argumentow i obecnosc funkcji dotdotdot
	var head_args, tail_args []reflect.Value
	if ft.IsVariadic() {
		num_in--
		if len(args) < num_in {
			return RUN_WRONG_ARG_NUM
		}
		head_args = args[0:num_in]
		tail_args = args[num_in:]
	} else {
		if num_in != len(args) {
			return RUN_WRONG_ARG_NUM
		}
		head_args = args
	}

	// Sprawdzamy zgodnosc typow poczatkowych argumentow funkcji
	for kk, av := range head_args {
		at := ft.In(kk + method) // Typ argumentu
		if !av.Type().AssignableTo(at) {
			return RUN_WRONG_ARG_TYP
		}
	}

	if !ft.IsVariadic() {
		return RUN_OK
	}

	// Okreslamy typ argumentów zawartych w dotdotdot
	st := ft.In(ft.NumIn() - 1) // zawsze slice
	at := st.Elem()             // Konkretny typ argumentu dotdotdot
	for _, av := range tail_args {
		if !av.Type().AssignableTo(at) {
			return RUN_WRONG_ARG_TYP
		}
	}

	return RUN_OK
}
Beispiel #8
0
func (info *Info) TypeInfo(t reflect.Type) *Type {
	var name TypeName
	if t.Name() != "" {
		name = mkName(t.PkgPath(), t.Name())
	}
	inPackage := t.PkgPath() != ""
	if inPackage && name != "" {
		if oldt := info.Types[name]; oldt != nil {
			if oldt.goType != nil && oldt.goType != t {
				panic(fmt.Errorf("duplicate type name with different types %q (%v)", name, t))
			}
			return oldt
		}
	}
	jt := &Type{
		Name:   name,
		Kind:   Kind(t.Kind().String()),
		goType: t,
	}
	if inPackage && name != "" {
		// Add the type to the info first to prevent infinite recursion.
		info.Types[name] = jt
	}
	info.addMethods(jt, t)
	switch t.Kind() {
	case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice:
		jt.Elem = info.Ref(t.Elem())
	case reflect.Map:
		jt.Key, jt.Elem = info.Ref(t.Key()), info.Ref(t.Elem())
	case reflect.Struct:
		info.addFields(jt, t)
	case reflect.Func:
		jt.Variadic = t.IsVariadic()
		jt.In = make([]*Type, t.NumIn())
		for i := range jt.In {
			jt.In[i] = info.Ref(t.In(i))
		}
		jt.Out = make([]*Type, t.NumOut())
		for i := range jt.Out {
			jt.Out[i] = info.Ref(t.Out(i))
		}
	}
	return jt
}
Beispiel #9
0
// getArgs retrieves argument list from args.
// This tries to avoid common panics, and returns the corresponding errors instead.
// panics can still occur but at least the ones related with arguments are mitigated.
func getlArgs(typ reflect.Type, args []interface{}) ([]reflect.Value, error) {
	var rst []reflect.Value
	for _, v := range args {
		val := reflect.ValueOf(v)
		if !val.IsValid() { // eliminate zero value panic
			return nil, ErrZeroValue
		}
		rst = append(rst, val)
	}
	switch {
	case typ.IsVariadic():
		if typ.NumIn() < len(args)-1 { // eliminate few argumenst panic
			return nil, ErrTooFewArgs
		}
	case !typ.IsVariadic() && typ.NumIn() > len(args): // eliminate too many arguments panic
		return nil, ErrTooManyArgs
	}
	return rst, nil
}
func (r JSONCaller) extractMethodArgs(runMethodType reflect.Type, args []interface{}) (methodArgs []reflect.Value, err error) {
	numberOfArgs := runMethodType.NumIn()
	numberOfReqArgs := numberOfArgs

	if runMethodType.IsVariadic() {
		numberOfReqArgs--
	}

	if len(args) < numberOfReqArgs {
		err = bosherr.Errorf("Not enough arguments, expected %d, got %d", numberOfReqArgs, len(args))
		return
	}

	for i, argFromPayload := range args {
		var rawArgBytes []byte

		rawArgBytes, err = json.Marshal(argFromPayload)
		if err != nil {
			err = bosherr.WrapError(err, "Marshalling action argument")
			return
		}

		argType, typeFound := r.getMethodArgType(runMethodType, i)
		if !typeFound {
			continue
		}

		argValuePtr := reflect.New(argType)

		err = json.Unmarshal(rawArgBytes, argValuePtr.Interface())
		if err != nil {
			err = bosherr.WrapError(err, "Unmarshalling action argument")
			return
		}

		methodArgs = append(methodArgs, reflect.Indirect(argValuePtr))
	}

	return
}
Beispiel #11
0
func newCtor(t reflect.Type, v reflect.Value) *ctor {
	if t.Kind() != reflect.Func || t.IsVariadic() {
		return nil
	}
	numOut := t.NumOut()
	if numOut == 0 || numOut > 2 || (numOut == 2 && t.Out(1) != terror) {
		return nil
	}
	outType := t.Out(0)
	numIn := t.NumIn()
	inTypes := make([]reflect.Type, numIn)
	for i := range inTypes {
		inTypes[i] = t.In(i)
	}
	construct := func(in []reflect.Value) (reflect.Value, error) {
		for i, arg := range in {
			if !arg.IsValid() {
				return reflect.Value{},
					fmt.Errorf("unable to create arg %d (%s) of %s constructor <%v>",
						i, inTypes[i], outType, arg)
			}
		}
		out := v.Call(in)
		var err error
		if len(out) == 2 && !out[1].IsNil() {
			err = out[1].Interface().(error)
		}
		return out[0], err
	}
	return &ctor{
		funcType:  t,
		outType:   outType,
		inTypes:   inTypes,
		construct: construct,
		errChan:   make(chan error),
		once:      &sync.Once{},
	}
}
Beispiel #12
0
func (L *State) getFuncIn(ft rf.Type) []rf.Value {
	var in []rf.Value
	var i int
	for i = 0; i < ft.NumIn()-1; i++ {
		in = append(in, *L.getValueByType(ft.In(i).Kind(), i))
	}

	switch {
	case ft.IsVariadic():
		ek := ft.In(i).Elem().Kind()
		for ; i < int(C.lua_gettop(L.s)); i++ {
			switch ek {
			case rf.Interface:
				in = append(in, *L.getValueByLuaType(i))
			default:
				in = append(in, *L.getValueByType(ek, i))
			}
		}
	case i < ft.NumIn():
		in = append(in, *L.getValueByType(ft.In(i).Kind(), i))
	}
	return in
}
Beispiel #13
0
func buildFactoryCallArguments(t reflect.Type, allParameters []interface{}) ([]reflect.Value, error) {
	actualNumberOfArgs := t.NumIn()
	args := make([]reflect.Value, len(allParameters))
	for i, argument := range allParameters {
		var expectedArgumentType reflect.Type
		if t.IsVariadic() && i >= actualNumberOfArgs-1 {
			// variadic argument
			expectedArgumentType = t.In(actualNumberOfArgs - 1).Elem()
		} else {
			// regular argument
			expectedArgumentType = t.In(i)
		}

		args[i] = reflect.ValueOf(argument)
		if args[i].Kind() != expectedArgumentType.Kind() {
			if stringArg, isString := argument.(string); isString && !IsParameterOrTypeReference(stringArg) {
				return nil, fmt.Errorf("input argument %d is of type %s but needs to be a %s", i+1, args[i].Kind(), expectedArgumentType.Kind())
			}
		}
	}

	return args, nil
}
Beispiel #14
0
// TypeFromNative converts a regular Go type into a the corresponding
// interpreter Type.
func TypeFromNative(t reflect.Type) Type {
	if et, ok := evalTypes[t]; ok {
		return et
	}

	var nt *NamedType
	if t.Name() != "" {
		name := t.PkgPath() + "·" + t.Name()
		nt = &NamedType{token.NoPos, name, nil, true, make(map[string]Method)}
		evalTypes[t] = nt
	}

	var et Type
	switch t.Kind() {
	case reflect.Bool:
		et = BoolType

	case reflect.Float32:
		et = Float32Type
	case reflect.Float64:
		et = Float64Type

	case reflect.Int16:
		et = Int16Type
	case reflect.Int32:
		et = Int32Type
	case reflect.Int64:
		et = Int64Type
	case reflect.Int8:
		et = Int8Type
	case reflect.Int:
		et = IntType

	case reflect.Uint16:
		et = Uint16Type
	case reflect.Uint32:
		et = Uint32Type
	case reflect.Uint64:
		et = Uint64Type
	case reflect.Uint8:
		et = Uint8Type
	case reflect.Uint:
		et = UintType
	case reflect.Uintptr:
		et = UintptrType

	case reflect.String:
		et = StringType
	case reflect.Array:
		et = NewArrayType(int64(t.Len()), TypeFromNative(t.Elem()))
	case reflect.Chan:
		log.Panicf("%T not implemented", t)
	case reflect.Func:
		nin := t.NumIn()
		// Variadic functions have DotDotDotType at the end
		variadic := t.IsVariadic()
		if variadic {
			nin--
		}
		in := make([]Type, nin)
		for i := range in {
			in[i] = TypeFromNative(t.In(i))
		}
		out := make([]Type, t.NumOut())
		for i := range out {
			out[i] = TypeFromNative(t.Out(i))
		}
		et = NewFuncType(in, variadic, out)
	case reflect.Interface:
		log.Panicf("%T not implemented", t)
	case reflect.Map:
		et = NewMapType(TypeFromNative(t.Key()), TypeFromNative(t.Elem()))
	case reflect.Ptr:
		et = NewPtrType(TypeFromNative(t.Elem()))
	case reflect.Slice:
		et = NewSliceType(TypeFromNative(t.Elem()))
	case reflect.Struct:
		n := t.NumField()
		fields := make([]StructField, n)
		for i := 0; i < n; i++ {
			sf := t.Field(i)
			// TODO(austin) What to do about private fields?
			fields[i].Name = sf.Name
			fields[i].Type = TypeFromNative(sf.Type)
			fields[i].Anonymous = sf.Anonymous
		}
		et = NewStructType(fields)
	case reflect.UnsafePointer:
		log.Panicf("%T not implemented", t)
	default:
		log.Panicf("unexpected reflect.Type: %T", t)
	}

	if nt != nil {
		if _, ok := et.(*NamedType); !ok {
			nt.Complete(et)
			et = nt
		}
	}

	nativeTypes[et] = t
	evalTypes[t] = et

	return et
}
Beispiel #15
0
func (p *Call) call(push bool, is []interface{}) (caller Caller) {
	defer func() {
		if err := recover(); err != nil {
			p.err = errors.New(fmt.Sprint(err))
		}
	}()
	caller = p
	if p.failed || p.err != nil || len(is) == 0 {
		return
	}
	var fn reflect.Value
	var typ reflect.Type
	l := len(is)
	for i := 0; i < l; {
		fn = reflect.ValueOf(is[i])
		if reflect.Func != fn.Kind() {
			p.args = append(p.args, is[i])
			i++
			continue
		}
		typ = fn.Type()
		la := typ.NumIn()
		numIn := 0
		if typ.IsVariadic() || la != 0 {
			for j := 0; typ.IsVariadic() || j < la; j++ {
				i++
				if i >= l || reflect.Func == reflect.TypeOf(is[i]).Kind() {
					break
				}
				p.args = append(p.args, is[i])
				numIn++
			}
		} else if la == 0 {
			i++
		}

		la = len(p.args)
		if la < typ.NumIn() {
			p.setFailed(NotEnoughArgs)
			break
		}
		if !typ.IsVariadic() {
			numIn = typ.NumIn()
		}

		args := p.args[la-numIn:]
		p.args = p.args[:la-numIn]

		in := make([]reflect.Value, len(args))
		for i, v := range args {
			in[i] = reflect.ValueOf(v)
		}

		out := fn.Call(in)
		la = len(out)

		// 总是保存输出
		o := make([]interface{}, la)
		for i, v := range out {
			o[i] = v.Interface()
		}
		p.outs = append(p.outs, o)
		if la == 0 {
			continue
		}

		fn = out[la-1]
		switch fn.Kind().String() {
		case "bool":
			if !fn.Bool() {
				p.setFailed(Failed)
				return
			}
			la--
		case "error":
			if !fn.IsNil() {
				p.setFailed(fn.Interface().(error))
				return
			}
			la--
		}
		// 输出压入备用参数
		if !push {
			continue
		}

		for i := 0; i < la; i++ {
			p.args = append(p.args, out[i].Interface())
		}
	}
	return
}
Beispiel #16
0
func (client *BaseClient) remoteMethod(t reflect.Type, sf reflect.StructField) func(in []reflect.Value) []reflect.Value {
	name := getFuncName(&sf)
	options := &InvokeOptions{ByRef: getByRef(&sf), SimpleMode: getSimpleMode(&sf), ResultMode: getResultMode(&sf)}
	return func(in []reflect.Value) []reflect.Value {
		inlen := len(in)
		varlen := 0
		argc := inlen
		if t.IsVariadic() {
			argc--
			varlen = in[argc].Len()
			argc += varlen
		}
		args := make([]reflect.Value, argc)
		if argc > 0 {
			for i := 0; i < inlen-1; i++ {
				args[i] = in[i]
			}
			if t.IsVariadic() {
				v := in[inlen-1]
				for i := 0; i < varlen; i++ {
					args[inlen-1+i] = v.Index(i)
				}
			} else {
				args[inlen-1] = in[inlen-1]
			}
		}
		numout := t.NumOut()
		out := make([]reflect.Value, numout)
		switch numout {
		case 0:
			var result interface{}
			if err := <-client.invoke(name, args, options, []reflect.Value{reflect.ValueOf(&result).Elem()}); err == nil {
				return out
			} else {
				panic(err.Error())
			}
		case 1:
			rt0 := t.Out(0)
			if rt0.Kind() == reflect.Chan {
				if rt0.Elem().Kind() == reflect.Interface && rt0.Elem().Name() == "error" {
					var result chan interface{}
					err := client.invoke(name, args, options, []reflect.Value{reflect.ValueOf(&result).Elem()})
					out[0] = reflect.ValueOf(&err).Elem()
					return out
				} else {
					out[0] = reflect.New(rt0).Elem()
					client.invoke(name, args, options, out)
					return out
				}
			} else {
				if rt0.Kind() == reflect.Interface && rt0.Name() == "error" {
					var result interface{}
					err := <-client.invoke(name, args, options, []reflect.Value{reflect.ValueOf(&result).Elem()})
					out[0] = reflect.ValueOf(&err).Elem()
					return out
				} else {
					out[0] = reflect.New(rt0).Elem()
					if err := <-client.invoke(name, args, options, out); err == nil {
						return out
					} else {
						panic(err.Error())
					}
				}
			}
		default:
			last := numout - 1
			rtlast := t.Out(last)
			for i := 0; i < last; i++ {
				out[i] = reflect.New(t.Out(i)).Elem()
			}
			if rtlast.Kind() == reflect.Chan &&
				rtlast.Elem().Kind() == reflect.Interface &&
				rtlast.Elem().Name() == "error" {
				err := client.invoke(name, args, options, out[:last])
				out[last] = reflect.ValueOf(&err).Elem()
				return out
			}
			if rtlast.Kind() == reflect.Interface &&
				rtlast.Name() == "error" {
				err := <-client.invoke(name, args, options, out[:last])
				out[last] = reflect.ValueOf(&err).Elem()
				return out
			}
			out[last] = reflect.New(t.Out(last)).Elem()
			if t.Out(0).Kind() == reflect.Chan {
				client.invoke(name, args, options, out)
				return out
			} else {
				if err := <-client.invoke(name, args, options, out); err == nil {
					return out
				} else {
					panic(err.Error())
				}
			}
		}
		return out
	}
}
Beispiel #17
0
func inType(call reflect.Type, nthArg int) reflect.Type {
	if call.IsVariadic() && nthArg >= call.NumIn()-1 {
		return call.In(call.NumIn() - 1).Elem()
	}
	return call.In(nthArg)
}
Beispiel #18
0
// argType returns the type of the nth argument to a function of type t.
func argType(t reflect.Type, n int) reflect.Type {
	if !t.IsVariadic() || n < t.NumIn()-1 {
		return t.In(n)
	}
	return t.In(t.NumIn() - 1).Elem()
}
Beispiel #19
0
func makeTrampoline(typ reflect.Type, handle unsafe.Pointer) (rFunc, error) {
	numOut := typ.NumOut()
	if numOut > 1 {
		return nil, fmt.Errorf("C functions can return 0 or 1 values, not %d", numOut)
	}
	var out reflect.Type
	var kind reflect.Kind
	outFlag := C.int(0)
	if numOut == 1 {
		out = typ.Out(0)
		kind = out.Kind()
		if kind == reflect.Float32 || kind == reflect.Float64 {
			outFlag |= C.ARG_FLAG_FLOAT
		}
	}
	return func(in []reflect.Value) []reflect.Value {
		if typ.IsVariadic() && len(in) > 0 {
			last := in[len(in)-1]
			in = in[:len(in)-1]
			if last.Len() > 0 {
				for ii := 0; ii < last.Len(); ii++ {
					in = append(in, last.Index(ii))
				}
			}
		}
		count := len(in)
		args := make([]unsafe.Pointer, count)
		flags := make([]C.int, count+1)
		flags[count] = outFlag
		for ii, v := range in {
			if v.Type() == emptyType {
				v = reflect.ValueOf(v.Interface())
			}
			switch v.Kind() {
			case reflect.String:
				s := C.CString(v.String())
				defer C.free(unsafe.Pointer(s))
				args[ii] = unsafe.Pointer(s)
				flags[ii] |= C.ARG_FLAG_SIZE_PTR
			case reflect.Int:
				args[ii] = unsafe.Pointer(uintptr(v.Int()))
				if v.Type().Size() == 4 {
					flags[ii] = C.ARG_FLAG_SIZE_32
				} else {
					flags[ii] = C.ARG_FLAG_SIZE_64
				}
			case reflect.Int8:
				args[ii] = unsafe.Pointer(uintptr(v.Int()))
				flags[ii] = C.ARG_FLAG_SIZE_8
			case reflect.Int16:
				args[ii] = unsafe.Pointer(uintptr(v.Int()))
				flags[ii] = C.ARG_FLAG_SIZE_16
			case reflect.Int32:
				args[ii] = unsafe.Pointer(uintptr(v.Int()))
				flags[ii] = C.ARG_FLAG_SIZE_32
			case reflect.Int64:
				args[ii] = unsafe.Pointer(uintptr(v.Int()))
				flags[ii] = C.ARG_FLAG_SIZE_64
			case reflect.Uint:
				args[ii] = unsafe.Pointer(uintptr(v.Uint()))
				if v.Type().Size() == 4 {
					flags[ii] = C.ARG_FLAG_SIZE_32
				} else {
					flags[ii] = C.ARG_FLAG_SIZE_64
				}
			case reflect.Uint8:
				args[ii] = unsafe.Pointer(uintptr(v.Uint()))
				flags[ii] = C.ARG_FLAG_SIZE_8
			case reflect.Uint16:
				args[ii] = unsafe.Pointer(uintptr(v.Uint()))
				flags[ii] = C.ARG_FLAG_SIZE_16
			case reflect.Uint32:
				args[ii] = unsafe.Pointer(uintptr(v.Uint()))
				flags[ii] = C.ARG_FLAG_SIZE_32
			case reflect.Uint64:
				args[ii] = unsafe.Pointer(uintptr(v.Uint()))
				flags[ii] = C.ARG_FLAG_SIZE_64
			case reflect.Float32:
				args[ii] = unsafe.Pointer(uintptr(math.Float32bits(float32(v.Float()))))
				flags[ii] |= C.ARG_FLAG_FLOAT | C.ARG_FLAG_SIZE_32
			case reflect.Float64:
				args[ii] = unsafe.Pointer(uintptr(math.Float64bits(v.Float())))
				flags[ii] |= C.ARG_FLAG_FLOAT | C.ARG_FLAG_SIZE_64
			case reflect.Ptr:
				args[ii] = unsafe.Pointer(v.Pointer())
				flags[ii] |= C.ARG_FLAG_SIZE_PTR
			case reflect.Slice:
				if v.Len() > 0 {
					args[ii] = unsafe.Pointer(v.Index(0).UnsafeAddr())
				}
				flags[ii] |= C.ARG_FLAG_SIZE_PTR
			case reflect.Uintptr:
				args[ii] = unsafe.Pointer(uintptr(v.Uint()))
				flags[ii] |= C.ARG_FLAG_SIZE_PTR
			default:
				panic(fmt.Errorf("can't bind value of type %s", v.Type()))
			}
		}
		var argp *unsafe.Pointer
		if count > 0 {
			argp = &args[0]
		}
		var ret unsafe.Pointer
		if C.call(handle, argp, &flags[0], C.int(count), &ret) != 0 {
			s := C.GoString((*C.char)(ret))
			C.free(ret)
			panic(errors.New(s))
		}
		if numOut > 0 {
			var v reflect.Value
			switch kind {
			case reflect.Int:
				v = reflect.ValueOf(int(uintptr(ret)))
			case reflect.Int8:
				v = reflect.ValueOf(int8(uintptr(ret)))
			case reflect.Int16:
				v = reflect.ValueOf(int16(uintptr(ret)))
			case reflect.Int32:
				v = reflect.ValueOf(int32(uintptr(ret)))
			case reflect.Int64:
				v = reflect.ValueOf(int64(uintptr(ret)))
			case reflect.Uint:
				v = reflect.ValueOf(uint(uintptr(ret)))
			case reflect.Uint8:
				v = reflect.ValueOf(uint8(uintptr(ret)))
			case reflect.Uint16:
				v = reflect.ValueOf(uint16(uintptr(ret)))
			case reflect.Uint32:
				v = reflect.ValueOf(uint32(uintptr(ret)))
			case reflect.Uint64:
				v = reflect.ValueOf(uint64(uintptr(ret)))
			case reflect.Float32:
				v = reflect.ValueOf(math.Float32frombits(uint32(uintptr(ret))))
			case reflect.Float64:
				v = reflect.ValueOf(math.Float64frombits(uint64(uintptr(ret))))
			case reflect.Ptr:
				if out.Elem().Kind() == reflect.String && ret != nil {
					s := C.GoString((*C.char)(ret))
					v = reflect.ValueOf(&s)
					break
				}
				v = reflect.NewAt(out.Elem(), ret)
			case reflect.String:
				s := C.GoString((*C.char)(ret))
				v = reflect.ValueOf(s)
			case reflect.Uintptr:
				v = reflect.ValueOf(uintptr(ret))
			case reflect.UnsafePointer:
				v = reflect.ValueOf(ret)
			default:
				panic(fmt.Errorf("can't retrieve value of type %s", out))
			}
			return []reflect.Value{v}
		}
		return nil
	}, nil
}