github.com/F4RD1N/gomobile@v1.0.1/bind/genobjcw.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package bind 6 7 import ( 8 "path" 9 "strings" 10 11 "github.com/F4RD1N/gomobile/internal/importers/objc" 12 ) 13 14 type ( 15 // ObjCWrapper generates Go and C stubs for ObjC interfaces and protocols. 16 ObjcWrapper struct { 17 *Printer 18 imported map[string]*objc.Named 19 // The list of ObjC types. 20 types []*objc.Named 21 // The list of Go package paths with ObjC wrappers. 22 pkgNames []string 23 modules []string 24 // For each ObjC module, the list of ObjC types within. 25 modMap map[string][]*objc.Named 26 // For each module/name Go package path, the ObjC type 27 // with static functions or constants. 28 typePkgs map[string]*objc.Named 29 // supers is the map of types that need Super methods. 30 supers map[string]struct{} 31 } 32 ) 33 34 // Init initializes the ObjC types wrapper generator. Types is the 35 // list of types to wrap, genNames the list of generated type names. 36 func (g *ObjcWrapper) Init(types []*objc.Named, genNames []string) { 37 g.supers = make(map[string]struct{}) 38 for _, s := range genNames { 39 g.supers[s] = struct{}{} 40 } 41 g.types = types 42 g.imported = make(map[string]*objc.Named) 43 g.modMap = make(map[string][]*objc.Named) 44 g.typePkgs = make(map[string]*objc.Named) 45 pkgSet := make(map[string]struct{}) 46 for _, n := range types { 47 g.imported[n.GoName] = n 48 typePkg := n.Module + "/" + n.GoName 49 g.typePkgs[typePkg] = n 50 if !n.Generated { 51 if _, exists := g.modMap[n.Module]; !exists { 52 g.modules = append(g.modules, n.Module) 53 } 54 } 55 g.modMap[n.Module] = append(g.modMap[n.Module], n) 56 if _, exists := pkgSet[n.Module]; !exists { 57 pkgSet[n.Module] = struct{}{} 58 g.pkgNames = append(g.pkgNames, n.Module) 59 } 60 g.pkgNames = append(g.pkgNames, typePkg) 61 } 62 } 63 64 func (g *ObjcWrapper) GenM() { 65 g.Printf(gobindPreamble) 66 // For objc_msgSend* functions. 67 g.Printf("@import ObjectiveC.message;\n") 68 g.Printf("#include \"seq.h\"\n") 69 g.Printf("#include \"interfaces.h\"\n\n") 70 for _, n := range g.types { 71 g.genM(n) 72 } 73 g.Printf("\n") 74 for _, n := range g.types { 75 for _, f := range n.AllMethods { 76 if !g.isFuncSupported(f) { 77 continue 78 } 79 g.genCFuncDecl("cproxy", n.GoName, f) 80 g.genCFuncBody(n, f, false) 81 if _, exists := g.supers[n.GoName]; exists { 82 g.genCFuncDecl("csuper", n.GoName, f) 83 g.genCFuncBody(n, f, true) 84 } 85 } 86 } 87 } 88 89 func (g *ObjcWrapper) genCFuncBody(n *objc.Named, f *objc.Func, super bool) { 90 g.Printf(" {\n") 91 g.Indent() 92 if !f.Static { 93 g.Printf("%s _this = go_seq_from_refnum(this).obj;\n", n.ObjcType()) 94 } 95 var errParam *objc.Param 96 for i, a := range f.Params { 97 if i == len(f.Params)-1 && g.isErrorType(a.Type) { 98 errParam = a 99 break 100 } 101 g.genCToObjC(a.Name, a.Type, modeTransient) 102 } 103 if errParam != nil { 104 g.Printf("NSError *%s = nil;\n", errParam.Name) 105 } 106 if f.Constructor { 107 g.Printf("%s _this = [%s alloc];\n", n.ObjcType(), n.Name) 108 } 109 if super { 110 g.Printf("struct objc_super _super = {\n") 111 g.Printf(" .receiver = _this,\n") 112 g.Printf(" .super_class = class_getSuperclass([%s class]),\n", n.Name) 113 g.Printf("};\n") 114 } 115 retType := "void" 116 if f.Ret != nil { 117 retType = g.objcType(f.Ret) 118 g.Printf("%s res = ", retType) 119 } 120 // There is no direct way to send a message to a class' super 121 // class from outside the class itself. Use objc_msgSendSuper instead 122 // which is what the compiler uses itself. To keep us honest and to exercise 123 // the code paths more use objc_msgSend for regular calls as well. 124 // 125 // A regular call looks like this: 126 // 127 // res = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSend)(_this, @selector(...), <arguments>) 128 // 129 // a call to super looks like this: 130 // 131 // ret = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSendSuper)(<struct objc_super>, <arguments>) 132 if f.Ret != nil { 133 switch f.Ret.Kind { 134 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: 135 default: 136 // If support for struct results is added, objc_msgSend_stret must be used 137 panic("unsupported type kind - use objc_msgSend_stret?") 138 } 139 } 140 g.Printf("((%s (*)(", retType) 141 if super { 142 g.Printf("struct objc_super *") 143 } else { 144 g.Printf("id") 145 } 146 g.Printf(", SEL") 147 for _, a := range f.Params { 148 g.Printf(", %s", g.objcType(a.Type)) 149 } 150 g.Printf("))") 151 if super { 152 g.Printf("objc_msgSendSuper") 153 } else { 154 g.Printf("objc_msgSend") 155 } 156 g.Printf(")(") 157 if f.Static && !f.Constructor { 158 g.Printf("[%s class]", n.Name) 159 } else { 160 if super { 161 g.Printf("&_super") 162 } else { 163 g.Printf("_this") 164 } 165 } 166 g.Printf(", @selector(%s)", f.Sig) 167 for _, a := range f.Params { 168 arg := "_" + a.Name 169 if a == errParam { 170 arg = "&" + a.Name 171 } 172 g.Printf(", %s", arg) 173 } 174 g.Printf(");\n") 175 if errParam != nil { 176 g.Printf("NSError *_%s = nil;\n", errParam.Name) 177 if f.Ret != nil { 178 g.Printf("if (!res && %s != nil) {\n", errParam.Name) 179 } else { 180 g.Printf("if (%s != nil) {\n", errParam.Name) 181 } 182 g.Printf(" _%[1]s = %[1]s;\n", errParam.Name) 183 g.Printf("}\n") 184 g.genObjCToC("_"+errParam.Name, g.errType(), modeRetained) 185 } 186 ret := f.Ret 187 if ret != nil && ret.Kind == objc.Bool && errParam != nil { 188 ret = nil 189 } 190 if ret != nil { 191 g.genObjCToC("res", ret, modeRetained) 192 } 193 switch { 194 case ret != nil && errParam != nil: 195 stype := strings.Replace(g.cType(ret), " ", "_", -1) 196 g.Printf("ret_%s _sres = {_res, __%s};\n", stype, errParam.Name) 197 g.Printf("return _sres;\n") 198 case ret != nil: 199 g.Printf("return _res;\n") 200 case errParam != nil: 201 g.Printf("return __%s;\n", errParam.Name) 202 } 203 g.Outdent() 204 g.Printf("}\n\n") 205 } 206 207 func (_ *ObjcWrapper) errType() *objc.Type { 208 return &objc.Type{Kind: objc.Class, Name: "NSError"} 209 } 210 211 func (g *ObjcWrapper) genM(n *objc.Named) { 212 for _, f := range n.Funcs { 213 if !g.isFuncSupported(f) { 214 continue 215 } 216 g.genCFuncDecl("cproxy", n.GoName, f) 217 g.genCFuncBody(n, f, false) 218 } 219 } 220 221 func (g *ObjcWrapper) GenH() { 222 g.Printf(gobindPreamble) 223 g.Printf("#include \"seq.h\"\n\n") 224 for _, m := range g.modules { 225 g.Printf("@import %s;\n", m) 226 } 227 // Include header files for generated types 228 for _, n := range g.pkgNames { 229 hasGen := false 230 for _, t := range g.modMap[n] { 231 if t.Generated { 232 hasGen = true 233 break 234 } 235 } 236 if hasGen { 237 g.Printf("#import %q\n", n+".objc.h") 238 } 239 } 240 for _, tn := range []string{"int", "nstring", "nbyteslice", "long", "unsigned long", "short", "unsigned short", "bool", "char", "unsigned char", "float", "double"} { 241 sn := strings.Replace(tn, " ", "_", -1) 242 g.Printf("typedef struct ret_%s {\n", sn) 243 g.Printf(" %s res;\n", tn) 244 g.Printf(" int err;\n") 245 g.Printf("} ret_%s;\n", sn) 246 } 247 g.Printf("\n") 248 for _, n := range g.types { 249 for _, f := range n.AllMethods { 250 if !g.isFuncSupported(f) { 251 continue 252 } 253 g.Printf("extern ") 254 g.genCFuncDecl("cproxy", n.GoName, f) 255 g.Printf(";\n") 256 if _, exists := g.supers[n.GoName]; exists { 257 g.Printf("extern ") 258 g.genCFuncDecl("csuper", n.GoName, f) 259 g.Printf(";\n") 260 } 261 } 262 } 263 for _, cls := range g.types { 264 g.genH(cls) 265 } 266 } 267 268 func (g *ObjcWrapper) genH(n *objc.Named) { 269 for _, f := range n.Funcs { 270 if !g.isFuncSupported(f) { 271 continue 272 } 273 g.Printf("extern ") 274 g.genCFuncDecl("cproxy", n.GoName, f) 275 g.Printf(";\n") 276 } 277 } 278 279 func (g *ObjcWrapper) genCFuncDecl(prefix, name string, f *objc.Func) { 280 returnsErr := len(f.Params) > 0 && g.isErrorType(f.Params[len(f.Params)-1].Type) 281 ret := f.Ret 282 if ret != nil && returnsErr && ret.Kind == objc.Bool { 283 ret = nil 284 } 285 switch { 286 case ret != nil && returnsErr: 287 g.Printf("ret_%s", strings.Replace(g.cType(ret), " ", "_", -1)) 288 case ret != nil: 289 g.Printf(g.cType(ret)) 290 case returnsErr: 291 g.Printf("int") 292 default: 293 g.Printf("void") 294 } 295 g.Printf(" ") 296 g.Printf(prefix) 297 if f.Static { 298 g.Printf("_s") 299 } 300 g.Printf("_%s_%s(", name, f.GoName) 301 if !f.Static { 302 g.Printf("int this") 303 } 304 for i, p := range f.Params { 305 if i == len(f.Params)-1 && returnsErr { 306 break 307 } 308 if !f.Static || i > 0 { 309 g.Printf(", ") 310 } 311 g.Printf("%s %s", g.cType(p.Type), p.Name) 312 } 313 g.Printf(")") 314 } 315 316 func (g *ObjcWrapper) GenGo() { 317 g.Printf(gobindPreamble) 318 g.Printf("package main\n\n") 319 g.Printf("// #include \"interfaces.h\"\n") 320 g.Printf("import \"C\"\n\n") 321 g.Printf("import \"ObjC\"\n") 322 g.Printf("import _seq \"github.com/F4RD1N/gomobile/bind/seq\"\n") 323 324 for _, n := range g.types { 325 for _, f := range n.Funcs { 326 if g.isFuncSupported(f) { 327 pkgName := n.Module + "/" + n.GoName 328 g.Printf("import %q\n", "ObjC/"+pkgName) 329 break 330 } 331 } 332 } 333 g.Printf("\n") 334 g.Printf("type proxy interface { Bind_proxy_refnum__() int32 }\n\n") 335 g.Printf("// Suppress unused package error\n\n") 336 g.Printf("var _ = _seq.FromRefNum\n") 337 g.Printf("const _ = ObjC.Dummy\n\n") 338 for _, n := range g.types { 339 g.genGo(n) 340 } 341 } 342 343 func (g *ObjcWrapper) genGo(n *objc.Named) { 344 g.Printf("func init() {\n") 345 g.Indent() 346 for _, f := range n.Funcs { 347 if !g.isFuncSupported(f) { 348 continue 349 } 350 g.Printf("%s.%s = func", n.GoName, f.GoName) 351 g.genFuncDecl(false, f) 352 g.genFuncBody(n, f, "cproxy") 353 } 354 g.Outdent() 355 g.Printf("}\n\n") 356 g.Printf("type proxy_class_%s _seq.Ref\n\n", n.GoName) 357 g.Printf("func (p *proxy_class_%s) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }\n\n", n.GoName) 358 for _, f := range n.AllMethods { 359 if !g.isFuncSupported(f) { 360 continue 361 } 362 g.Printf("func (p *proxy_class_%s) %s", n.GoName, f.GoName) 363 g.genFuncDecl(false, f) 364 g.genFuncBody(n, f, "cproxy") 365 } 366 if _, exists := g.supers[n.GoName]; exists { 367 g.Printf("func (p *proxy_class_%s) Super() ObjC.%s {\n", n.GoName, n.Module+"_"+n.GoName) 368 g.Printf(" return &super_%s{p}\n", n.GoName) 369 g.Printf("}\n\n") 370 g.Printf("type super_%s struct {*proxy_class_%[1]s}\n\n", n.GoName) 371 for _, f := range n.AllMethods { 372 if !g.isFuncSupported(f) { 373 continue 374 } 375 g.Printf("func (p *super_%s) %s", n.GoName, f.GoName) 376 g.genFuncDecl(false, f) 377 g.genFuncBody(n, f, "csuper") 378 } 379 } 380 } 381 382 func (g *ObjcWrapper) genFuncBody(n *objc.Named, f *objc.Func, prefix string) { 383 g.Printf(" {\n") 384 g.Indent() 385 var errParam *objc.Param 386 for i, a := range f.Params { 387 if i == len(f.Params)-1 && g.isErrorType(a.Type) { 388 errParam = a 389 break 390 } 391 g.genWrite(a) 392 } 393 ret := f.Ret 394 if ret != nil && errParam != nil && ret.Kind == objc.Bool { 395 ret = nil 396 } 397 if ret != nil || errParam != nil { 398 g.Printf("res := ") 399 } 400 g.Printf("C.") 401 g.Printf(prefix) 402 if f.Static { 403 g.Printf("_s") 404 } 405 g.Printf("_%s_%s(", n.GoName, f.GoName) 406 if !f.Static { 407 g.Printf("C.int(p.Bind_proxy_refnum__())") 408 } 409 for i, a := range f.Params { 410 if a == errParam { 411 break 412 } 413 if !f.Static || i > 0 { 414 g.Printf(", ") 415 } 416 g.Printf("_%s", a.Name) 417 } 418 g.Printf(")\n") 419 switch { 420 case ret != nil && errParam != nil: 421 g.genRead("_res", "res.res", ret) 422 g.genRefRead("_"+errParam.Name, "res.err", "error", "proxy_error") 423 g.Printf("return _res, _%s\n", errParam.Name) 424 case ret != nil: 425 g.genRead("_res", "res", ret) 426 g.Printf("return _res\n") 427 case errParam != nil: 428 g.genRefRead("_"+errParam.Name, "res", "error", "proxy_error") 429 g.Printf("return _%s\n", errParam.Name) 430 } 431 g.Outdent() 432 g.Printf("}\n\n") 433 } 434 435 func (g *ObjcWrapper) genCToObjC(name string, t *objc.Type, mode varMode) { 436 switch t.Kind { 437 case objc.String: 438 g.Printf("NSString *_%s = go_seq_to_objc_string(%s);\n", name, name) 439 case objc.Bool: 440 g.Printf("BOOL _%s = %s ? YES : NO;\n", name, name) 441 case objc.Data: 442 g.Printf("NSData *_%s = go_seq_to_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained)) 443 case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double: 444 g.Printf("%s _%s = (%s)%s;\n", g.objcType(t), name, g.objcType(t), name) 445 case objc.Class, objc.Protocol: 446 g.Printf("GoSeqRef* %s_ref = go_seq_from_refnum(%s);\n", name, name) 447 g.Printf("%s _%s;\n", g.objcType(t), name) 448 g.Printf("if (%s_ref != NULL) {\n", name) 449 g.Printf(" _%s = %s_ref.obj;\n", name, name) 450 g.Printf("}\n") 451 default: 452 panic("invalid kind") 453 } 454 } 455 456 func (g *ObjcWrapper) genObjCToC(name string, t *objc.Type, mode varMode) { 457 switch t.Kind { 458 case objc.String: 459 g.Printf("nstring _%s = go_seq_from_objc_string(%s);\n", name, name) 460 case objc.Data: 461 g.Printf("nbyteslice _%s = go_seq_from_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained)) 462 case objc.Bool, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double: 463 g.Printf("%s _%s = (%s)%s;\n", g.cType(t), name, g.cType(t), name) 464 case objc.Protocol, objc.Class: 465 g.Printf("int _%s = go_seq_to_refnum(%s);\n", name, name) 466 default: 467 panic("invalid kind") 468 } 469 } 470 471 func (g *ObjcWrapper) genWrite(a *objc.Param) { 472 switch a.Type.Kind { 473 case objc.String: 474 g.Printf("_%s := encodeString(%s)\n", a.Name, a.Name) 475 case objc.Data: 476 g.Printf("_%s := fromSlice(%s, false)\n", a.Name, a.Name) 477 case objc.Bool: 478 g.Printf("_%s := %s(0)\n", a.Name, g.cgoType(a.Type)) 479 g.Printf("if %s {\n", a.Name) 480 g.Printf(" _%s = %s(1)\n", a.Name, g.cgoType(a.Type)) 481 g.Printf("}\n") 482 case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double: 483 g.Printf("_%s := %s(%s)\n", a.Name, g.cgoType(a.Type), a.Name) 484 case objc.Protocol, objc.Class: 485 g.Printf("var _%s %s = _seq.NullRefNum\n", a.Name, g.cgoType(a.Type)) 486 g.Printf("if %s != nil {\n", a.Name) 487 g.Printf(" _%s = %s(_seq.ToRefNum(%s))\n", a.Name, g.cgoType(a.Type), a.Name) 488 g.Printf("}\n") 489 default: 490 panic("invalid kind") 491 } 492 } 493 494 func (g *ObjcWrapper) genRead(to, from string, t *objc.Type) { 495 switch t.Kind { 496 case objc.Int, objc.Uint, objc.Uchar, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double: 497 g.Printf("%s := %s(%s)\n", to, g.goType(t, false), from) 498 case objc.Bool: 499 g.Printf("%s := %s != 0\n", to, from) 500 case objc.String: 501 g.Printf("%s := decodeString(%s)\n", to, from) 502 case objc.Data: 503 g.Printf("%s := toSlice(%s, true)\n", to, from) 504 case objc.Protocol, objc.Class: 505 var proxyName string 506 if n := g.lookupImported(t); n != nil { 507 proxyName = "proxy_class_" + n.GoName 508 } 509 g.genRefRead(to, from, g.goType(t, false), proxyName) 510 default: 511 panic("invalid kind") 512 } 513 } 514 515 func (g *ObjcWrapper) genRefRead(to, from string, intfName, proxyName string) { 516 g.Printf("var %s %s\n", to, intfName) 517 g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", to, from) 518 g.Printf("if %s_ref != nil {\n", to) 519 g.Printf(" if %s < 0 { // go object\n", from) 520 g.Printf(" %s = %s_ref.Get().(%s)\n", to, to, intfName) 521 if proxyName != "" { 522 g.Printf(" } else { // foreign object\n") 523 g.Printf(" %s = (*%s)(%s_ref)\n", to, proxyName, to) 524 } 525 g.Printf(" }\n") 526 g.Printf("}\n") 527 } 528 529 // Packages return the list of Go packages to be generated. 530 func (g *ObjcWrapper) Packages() []string { 531 return g.pkgNames 532 } 533 534 func (g *ObjcWrapper) GenPackage(idx int) { 535 pkg := g.pkgNames[idx] 536 g.Printf(gobindPreamble) 537 g.Printf("package %s\n\n", path.Base(pkg)) 538 g.Printf("import \"ObjC\"\n\n") 539 g.Printf("const _ = ObjC.Dummy\n\n") 540 for _, n := range g.modMap[pkg] { 541 g.Printf("type %s ObjC.%s\n", n.GoName, n.Module+"_"+n.GoName) 542 } 543 if n, ok := g.typePkgs[pkg]; ok { 544 g.Printf("var (\n") 545 g.Indent() 546 // Functions 547 for _, f := range n.Funcs { 548 if !g.isFuncSupported(f) { 549 continue 550 } 551 g.Printf("%s func", f.GoName) 552 g.genFuncDecl(false, f) 553 g.Printf("\n") 554 } 555 g.Outdent() 556 g.Printf(")\n\n") 557 } 558 } 559 560 func (g *ObjcWrapper) GenInterfaces() { 561 g.Printf(gobindPreamble) 562 g.Printf("package ObjC\n\n") 563 g.Printf("// Used to silence this package not used errors\n") 564 g.Printf("const Dummy = 0\n\n") 565 for _, n := range g.types { 566 g.genInterface(n) 567 } 568 } 569 570 func (g *ObjcWrapper) genInterface(n *objc.Named) { 571 g.Printf("type %s interface {\n", n.Module+"_"+n.GoName) 572 g.Indent() 573 // Methods 574 for _, f := range n.AllMethods { 575 if !g.isFuncSupported(f) { 576 continue 577 } 578 g.Printf(f.GoName) 579 g.genFuncDecl(true, f) 580 g.Printf("\n") 581 } 582 if _, exists := g.supers[n.GoName]; exists { 583 g.Printf("Super() %s\n", n.Module+"_"+n.GoName) 584 } 585 g.Outdent() 586 g.Printf("}\n\n") 587 } 588 589 func (g *ObjcWrapper) genFuncDecl(local bool, f *objc.Func) { 590 var returnsErr bool 591 g.Printf("(") 592 for i, p := range f.Params { 593 if i == len(f.Params)-1 && g.isErrorType(p.Type) { 594 returnsErr = true 595 break 596 } 597 if i > 0 { 598 g.Printf(", ") 599 } 600 g.Printf("%s %s", p.Name, g.goType(p.Type, local)) 601 } 602 g.Printf(")") 603 if f.Ret != nil || returnsErr { 604 ret := f.Ret 605 if ret.Kind == objc.Bool && returnsErr { 606 // Skip the bool result and use the error results. 607 ret = nil 608 } 609 if ret != nil { 610 g.Printf(" (%s", g.goType(f.Ret, local)) 611 if returnsErr { 612 g.Printf(", error") 613 } 614 g.Printf(")") 615 } else { 616 g.Printf(" error") 617 } 618 } 619 } 620 621 func (g *ObjcWrapper) isFuncSupported(f *objc.Func) bool { 622 for i, p := range f.Params { 623 if !g.isSupported(p.Type) { 624 if i < len(f.Params)-1 || !g.isErrorType(p.Type) { 625 return false 626 } 627 } 628 } 629 if f.Ret != nil { 630 return g.isSupported(f.Ret) 631 } 632 return true 633 } 634 635 func (g *ObjcWrapper) isErrorType(t *objc.Type) bool { 636 // Must be a NSError ** type 637 return t.Kind == objc.Class && t.Indirect && t.Name == "NSError" 638 } 639 640 func (g *ObjcWrapper) isSupported(t *objc.Type) bool { 641 if t.Indirect { 642 return false 643 } 644 switch t.Kind { 645 case objc.Unknown: 646 return false 647 case objc.Protocol: 648 // TODO: support inout parameters. 649 return !strings.HasSuffix(t.Decl, " *") 650 case objc.Class: 651 return t.Name != "SEL" && t.Name != "void" 652 default: 653 return true 654 } 655 } 656 657 func (g *ObjcWrapper) cgoType(t *objc.Type) string { 658 switch t.Kind { 659 case objc.Uint: 660 return "C.ulong" 661 case objc.Ushort: 662 return "C.ushort" 663 case objc.Uchar: 664 return "C.uchar" 665 default: 666 return "C." + g.cType(t) 667 } 668 } 669 670 func (g *ObjcWrapper) cType(t *objc.Type) string { 671 switch t.Kind { 672 case objc.Protocol, objc.Class: 673 return "int" 674 case objc.String: 675 return "nstring" 676 case objc.Data: 677 return "nbyteslice" 678 case objc.Int: 679 return "long" 680 case objc.Uint: 681 return "unsigned long" 682 case objc.Short: 683 return "short" 684 case objc.Ushort: 685 return "unsigned short" 686 case objc.Bool: 687 return "char" 688 case objc.Char: 689 return "char" 690 case objc.Uchar: 691 return "unsigned char" 692 case objc.Float: 693 return "float" 694 case objc.Double: 695 return "double" 696 default: 697 panic("invalid kind") 698 } 699 } 700 701 func (g *ObjcWrapper) objcType(t *objc.Type) string { 702 return t.Decl 703 } 704 705 func (g *ObjcWrapper) lookupImported(t *objc.Type) *objc.Named { 706 var mangled string 707 switch t.Kind { 708 case objc.Class: 709 mangled = t.Name + "C" 710 case objc.Protocol: 711 mangled = t.Name + "P" 712 default: 713 panic("invalid type kind") 714 } 715 if n, exists := g.imported[mangled]; exists { 716 return n 717 } 718 return g.imported[t.Name] 719 } 720 721 func (g *ObjcWrapper) goType(t *objc.Type, local bool) string { 722 switch t.Kind { 723 case objc.String: 724 return "string" 725 case objc.Data: 726 return "[]byte" 727 case objc.Int: 728 return "int" 729 case objc.Uint: 730 return "uint" 731 case objc.Short: 732 return "int16" 733 case objc.Ushort: 734 return "uint16" 735 case objc.Bool: 736 return "bool" 737 case objc.Char: 738 return "byte" 739 case objc.Uchar: 740 return "uint8" 741 case objc.Float: 742 return "float32" 743 case objc.Double: 744 return "float64" 745 case objc.Protocol, objc.Class: 746 var n *objc.Named 747 n = g.lookupImported(t) 748 name := n.Module + "_" + n.GoName 749 if !local { 750 name = "ObjC." + name 751 } 752 return name 753 default: 754 panic("invalid kind") 755 } 756 }