genobjcw.go 19 KB

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