func()

in bind/genobjcw.go [89:205]


func (g *ObjcWrapper) genCFuncBody(n *objc.Named, f *objc.Func, super bool) {
	g.Printf(" {\n")
	g.Indent()
	if !f.Static {
		g.Printf("%s _this = go_seq_from_refnum(this).obj;\n", n.ObjcType())
	}
	var errParam *objc.Param
	for i, a := range f.Params {
		if i == len(f.Params)-1 && g.isErrorType(a.Type) {
			errParam = a
			break
		}
		g.genCToObjC(a.Name, a.Type, modeTransient)
	}
	if errParam != nil {
		g.Printf("NSError *%s = nil;\n", errParam.Name)
	}
	if f.Constructor {
		g.Printf("%s _this = [%s alloc];\n", n.ObjcType(), n.Name)
	}
	if super {
		g.Printf("struct objc_super _super = {\n")
		g.Printf("	.receiver = _this,\n")
		g.Printf("	.super_class = class_getSuperclass([%s class]),\n", n.Name)
		g.Printf("};\n")
	}
	retType := "void"
	if f.Ret != nil {
		retType = g.objcType(f.Ret)
		g.Printf("%s res = ", retType)
	}
	// There is no direct way to send a message to a class' super
	// class from outside the class itself. Use objc_msgSendSuper instead
	// which is what the compiler uses itself. To keep us honest and to exercise
	// the code paths more use objc_msgSend for regular calls as well.
	//
	// A regular call looks like this:
	//
	// res = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSend)(_this, @selector(...), <arguments>)
	//
	// a call to super looks like this:
	//
	// ret = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSendSuper)(<struct objc_super>, <arguments>)
	if f.Ret != nil {
		switch f.Ret.Kind {
		case objc.String, objc.Bool, objc.Data, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double, objc.Class, objc.Protocol:
		default:
			// If support for struct results is added, objc_msgSend_stret must be used
			panic("unsupported type kind - use objc_msgSend_stret?")
		}
	}
	g.Printf("((%s (*)(", retType)
	if super {
		g.Printf("struct objc_super *")
	} else {
		g.Printf("id")
	}
	g.Printf(", SEL")
	for _, a := range f.Params {
		g.Printf(", %s", g.objcType(a.Type))
	}
	g.Printf("))")
	if super {
		g.Printf("objc_msgSendSuper")
	} else {
		g.Printf("objc_msgSend")
	}
	g.Printf(")(")
	if f.Static && !f.Constructor {
		g.Printf("[%s class]", n.Name)
	} else {
		if super {
			g.Printf("&_super")
		} else {
			g.Printf("_this")
		}
	}
	g.Printf(", @selector(%s)", f.Sig)
	for _, a := range f.Params {
		arg := "_" + a.Name
		if a == errParam {
			arg = "&" + a.Name
		}
		g.Printf(", %s", arg)
	}
	g.Printf(");\n")
	if errParam != nil {
		g.Printf("NSError *_%s = nil;\n", errParam.Name)
		if f.Ret != nil {
			g.Printf("if (!res && %s != nil) {\n", errParam.Name)
		} else {
			g.Printf("if (%s != nil) {\n", errParam.Name)
		}
		g.Printf("	_%[1]s = %[1]s;\n", errParam.Name)
		g.Printf("}\n")
		g.genObjCToC("_"+errParam.Name, g.errType(), modeRetained)
	}
	ret := f.Ret
	if ret != nil && ret.Kind == objc.Bool && errParam != nil {
		ret = nil
	}
	if ret != nil {
		g.genObjCToC("res", ret, modeRetained)
	}
	switch {
	case ret != nil && errParam != nil:
		stype := strings.Replace(g.cType(ret), " ", "_", -1)
		g.Printf("ret_%s _sres = {_res, __%s};\n", stype, errParam.Name)
		g.Printf("return _sres;\n")
	case ret != nil:
		g.Printf("return _res;\n")
	case errParam != nil:
		g.Printf("return __%s;\n", errParam.Name)
	}
	g.Outdent()
	g.Printf("}\n\n")
}