genobjcw.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  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("%s", g.cType(ret))
  278. case returnsErr:
  279. g.Printf("int")
  280. default:
  281. g.Printf("void")
  282. }
  283. g.Printf(" %s", prefix)
  284. if f.Static {
  285. g.Printf("_s")
  286. }
  287. g.Printf("_%s_%s(", name, f.GoName)
  288. if !f.Static {
  289. g.Printf("int this")
  290. }
  291. for i, p := range f.Params {
  292. if i == len(f.Params)-1 && returnsErr {
  293. break
  294. }
  295. if !f.Static || i > 0 {
  296. g.Printf(", ")
  297. }
  298. g.Printf("%s %s", g.cType(p.Type), p.Name)
  299. }
  300. g.Printf(")")
  301. }
  302. func (g *ObjcWrapper) GenGo() {
  303. g.Printf(gobindPreamble)
  304. g.Printf("package main\n\n")
  305. g.Printf("// #include \"interfaces.h\"\n")
  306. g.Printf("import \"C\"\n\n")
  307. g.Printf("import \"ObjC\"\n")
  308. g.Printf("import _seq \"golang.org/x/mobile/bind/seq\"\n")
  309. for _, n := range g.types {
  310. for _, f := range n.Funcs {
  311. if g.isFuncSupported(f) {
  312. pkgName := n.Module + "/" + n.GoName
  313. g.Printf("import %q\n", "ObjC/"+pkgName)
  314. break
  315. }
  316. }
  317. }
  318. g.Printf("\n")
  319. g.Printf("type proxy interface { Bind_proxy_refnum__() int32 }\n\n")
  320. g.Printf("// Suppress unused package error\n\n")
  321. g.Printf("var _ = _seq.FromRefNum\n")
  322. g.Printf("const _ = ObjC.Dummy\n\n")
  323. for _, n := range g.types {
  324. g.genGo(n)
  325. }
  326. }
  327. func (g *ObjcWrapper) genGo(n *objc.Named) {
  328. g.Printf("func init() {\n")
  329. g.Indent()
  330. for _, f := range n.Funcs {
  331. if !g.isFuncSupported(f) {
  332. continue
  333. }
  334. g.Printf("%s.%s = func", n.GoName, f.GoName)
  335. g.genFuncDecl(false, f)
  336. g.genFuncBody(n, f, "cproxy")
  337. }
  338. g.Outdent()
  339. g.Printf("}\n\n")
  340. g.Printf("type proxy_class_%s _seq.Ref\n\n", n.GoName)
  341. g.Printf("func (p *proxy_class_%s) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }\n\n", n.GoName)
  342. for _, f := range n.AllMethods {
  343. if !g.isFuncSupported(f) {
  344. continue
  345. }
  346. g.Printf("func (p *proxy_class_%s) %s", n.GoName, f.GoName)
  347. g.genFuncDecl(false, f)
  348. g.genFuncBody(n, f, "cproxy")
  349. }
  350. if _, exists := g.supers[n.GoName]; exists {
  351. g.Printf("func (p *proxy_class_%s) Super() ObjC.%s {\n", n.GoName, n.Module+"_"+n.GoName)
  352. g.Printf(" return &super_%s{p}\n", n.GoName)
  353. g.Printf("}\n\n")
  354. g.Printf("type super_%s struct {*proxy_class_%[1]s}\n\n", n.GoName)
  355. for _, f := range n.AllMethods {
  356. if !g.isFuncSupported(f) {
  357. continue
  358. }
  359. g.Printf("func (p *super_%s) %s", n.GoName, f.GoName)
  360. g.genFuncDecl(false, f)
  361. g.genFuncBody(n, f, "csuper")
  362. }
  363. }
  364. }
  365. func (g *ObjcWrapper) genFuncBody(n *objc.Named, f *objc.Func, prefix string) {
  366. g.Printf(" {\n")
  367. g.Indent()
  368. var errParam *objc.Param
  369. for i, a := range f.Params {
  370. if i == len(f.Params)-1 && g.isErrorType(a.Type) {
  371. errParam = a
  372. break
  373. }
  374. g.genWrite(a)
  375. }
  376. ret := f.Ret
  377. if ret != nil && errParam != nil && ret.Kind == objc.Bool {
  378. ret = nil
  379. }
  380. if ret != nil || errParam != nil {
  381. g.Printf("res := ")
  382. }
  383. g.Printf("C.%s", prefix)
  384. if f.Static {
  385. g.Printf("_s")
  386. }
  387. g.Printf("_%s_%s(", n.GoName, f.GoName)
  388. if !f.Static {
  389. g.Printf("C.int(p.Bind_proxy_refnum__())")
  390. }
  391. for i, a := range f.Params {
  392. if a == errParam {
  393. break
  394. }
  395. if !f.Static || i > 0 {
  396. g.Printf(", ")
  397. }
  398. g.Printf("_%s", a.Name)
  399. }
  400. g.Printf(")\n")
  401. switch {
  402. case ret != nil && errParam != nil:
  403. g.genRead("_res", "res.res", ret)
  404. g.genRefRead("_"+errParam.Name, "res.err", "error", "proxy_error")
  405. g.Printf("return _res, _%s\n", errParam.Name)
  406. case ret != nil:
  407. g.genRead("_res", "res", ret)
  408. g.Printf("return _res\n")
  409. case errParam != nil:
  410. g.genRefRead("_"+errParam.Name, "res", "error", "proxy_error")
  411. g.Printf("return _%s\n", errParam.Name)
  412. }
  413. g.Outdent()
  414. g.Printf("}\n\n")
  415. }
  416. func (g *ObjcWrapper) genCToObjC(name string, t *objc.Type, mode varMode) {
  417. switch t.Kind {
  418. case objc.String:
  419. g.Printf("NSString *_%s = go_seq_to_objc_string(%s);\n", name, name)
  420. case objc.Bool:
  421. g.Printf("BOOL _%s = %s ? YES : NO;\n", name, name)
  422. case objc.Data:
  423. g.Printf("NSData *_%s = go_seq_to_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained))
  424. case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
  425. g.Printf("%s _%s = (%s)%s;\n", g.objcType(t), name, g.objcType(t), name)
  426. case objc.Class, objc.Protocol:
  427. g.Printf("GoSeqRef* %s_ref = go_seq_from_refnum(%s);\n", name, name)
  428. g.Printf("%s _%s;\n", g.objcType(t), name)
  429. g.Printf("if (%s_ref != NULL) {\n", name)
  430. g.Printf(" _%s = %s_ref.obj;\n", name, name)
  431. g.Printf("}\n")
  432. default:
  433. panic("invalid kind")
  434. }
  435. }
  436. func (g *ObjcWrapper) genObjCToC(name string, t *objc.Type, mode varMode) {
  437. switch t.Kind {
  438. case objc.String:
  439. g.Printf("nstring _%s = go_seq_from_objc_string(%s);\n", name, name)
  440. case objc.Data:
  441. g.Printf("nbyteslice _%s = go_seq_from_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained))
  442. case objc.Bool, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
  443. g.Printf("%s _%s = (%s)%s;\n", g.cType(t), name, g.cType(t), name)
  444. case objc.Protocol, objc.Class:
  445. g.Printf("int _%s = go_seq_to_refnum(%s);\n", name, name)
  446. default:
  447. panic("invalid kind")
  448. }
  449. }
  450. func (g *ObjcWrapper) genWrite(a *objc.Param) {
  451. switch a.Type.Kind {
  452. case objc.String:
  453. g.Printf("_%s := encodeString(%s)\n", a.Name, a.Name)
  454. case objc.Data:
  455. g.Printf("_%s := fromSlice(%s, false)\n", a.Name, a.Name)
  456. case objc.Bool:
  457. g.Printf("_%s := %s(0)\n", a.Name, g.cgoType(a.Type))
  458. g.Printf("if %s {\n", a.Name)
  459. g.Printf(" _%s = %s(1)\n", a.Name, g.cgoType(a.Type))
  460. g.Printf("}\n")
  461. case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
  462. g.Printf("_%s := %s(%s)\n", a.Name, g.cgoType(a.Type), a.Name)
  463. case objc.Protocol, objc.Class:
  464. g.Printf("var _%s %s = _seq.NullRefNum\n", a.Name, g.cgoType(a.Type))
  465. g.Printf("if %s != nil {\n", a.Name)
  466. g.Printf(" _%s = %s(_seq.ToRefNum(%s))\n", a.Name, g.cgoType(a.Type), a.Name)
  467. g.Printf("}\n")
  468. default:
  469. panic("invalid kind")
  470. }
  471. }
  472. func (g *ObjcWrapper) genRead(to, from string, t *objc.Type) {
  473. switch t.Kind {
  474. case objc.Int, objc.Uint, objc.Uchar, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
  475. g.Printf("%s := %s(%s)\n", to, g.goType(t, false), from)
  476. case objc.Bool:
  477. g.Printf("%s := %s != 0\n", to, from)
  478. case objc.String:
  479. g.Printf("%s := decodeString(%s)\n", to, from)
  480. case objc.Data:
  481. g.Printf("%s := toSlice(%s, true)\n", to, from)
  482. case objc.Protocol, objc.Class:
  483. var proxyName string
  484. if n := g.lookupImported(t); n != nil {
  485. proxyName = "proxy_class_" + n.GoName
  486. }
  487. g.genRefRead(to, from, g.goType(t, false), proxyName)
  488. default:
  489. panic("invalid kind")
  490. }
  491. }
  492. func (g *ObjcWrapper) genRefRead(to, from string, intfName, proxyName string) {
  493. g.Printf("var %s %s\n", to, intfName)
  494. g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", to, from)
  495. g.Printf("if %s_ref != nil {\n", to)
  496. g.Printf(" if %s < 0 { // go object\n", from)
  497. g.Printf(" %s = %s_ref.Get().(%s)\n", to, to, intfName)
  498. if proxyName != "" {
  499. g.Printf(" } else { // foreign object\n")
  500. g.Printf(" %s = (*%s)(%s_ref)\n", to, proxyName, to)
  501. }
  502. g.Printf(" }\n")
  503. g.Printf("}\n")
  504. }
  505. // Packages return the list of Go packages to be generated.
  506. func (g *ObjcWrapper) Packages() []string {
  507. return g.pkgNames
  508. }
  509. func (g *ObjcWrapper) GenPackage(idx int) {
  510. pkg := g.pkgNames[idx]
  511. g.Printf(gobindPreamble)
  512. g.Printf("package %s\n\n", path.Base(pkg))
  513. g.Printf("import \"ObjC\"\n\n")
  514. g.Printf("const _ = ObjC.Dummy\n\n")
  515. for _, n := range g.modMap[pkg] {
  516. g.Printf("type %s ObjC.%s\n", n.GoName, n.Module+"_"+n.GoName)
  517. }
  518. if n, ok := g.typePkgs[pkg]; ok {
  519. g.Printf("var (\n")
  520. g.Indent()
  521. // Functions
  522. for _, f := range n.Funcs {
  523. if !g.isFuncSupported(f) {
  524. continue
  525. }
  526. g.Printf("%s func", f.GoName)
  527. g.genFuncDecl(false, f)
  528. g.Printf("\n")
  529. }
  530. g.Outdent()
  531. g.Printf(")\n\n")
  532. }
  533. }
  534. func (g *ObjcWrapper) GenInterfaces() {
  535. g.Printf(gobindPreamble)
  536. g.Printf("package ObjC\n\n")
  537. g.Printf("// Used to silence this package not used errors\n")
  538. g.Printf("const Dummy = 0\n\n")
  539. for _, n := range g.types {
  540. g.genInterface(n)
  541. }
  542. }
  543. func (g *ObjcWrapper) genInterface(n *objc.Named) {
  544. g.Printf("type %s interface {\n", n.Module+"_"+n.GoName)
  545. g.Indent()
  546. // Methods
  547. for _, f := range n.AllMethods {
  548. if !g.isFuncSupported(f) {
  549. continue
  550. }
  551. g.Printf("%s", f.GoName)
  552. g.genFuncDecl(true, f)
  553. g.Printf("\n")
  554. }
  555. if _, exists := g.supers[n.GoName]; exists {
  556. g.Printf("Super() %s\n", n.Module+"_"+n.GoName)
  557. }
  558. g.Outdent()
  559. g.Printf("}\n\n")
  560. }
  561. func (g *ObjcWrapper) genFuncDecl(local bool, f *objc.Func) {
  562. var returnsErr bool
  563. g.Printf("(")
  564. for i, p := range f.Params {
  565. if i == len(f.Params)-1 && g.isErrorType(p.Type) {
  566. returnsErr = true
  567. break
  568. }
  569. if i > 0 {
  570. g.Printf(", ")
  571. }
  572. g.Printf("%s %s", p.Name, g.goType(p.Type, local))
  573. }
  574. g.Printf(")")
  575. if f.Ret != nil || returnsErr {
  576. ret := f.Ret
  577. if ret.Kind == objc.Bool && returnsErr {
  578. // Skip the bool result and use the error results.
  579. ret = nil
  580. }
  581. if ret != nil {
  582. g.Printf(" (%s", g.goType(f.Ret, local))
  583. if returnsErr {
  584. g.Printf(", error")
  585. }
  586. g.Printf(")")
  587. } else {
  588. g.Printf(" error")
  589. }
  590. }
  591. }
  592. func (g *ObjcWrapper) isFuncSupported(f *objc.Func) bool {
  593. for i, p := range f.Params {
  594. if !g.isSupported(p.Type) {
  595. if i < len(f.Params)-1 || !g.isErrorType(p.Type) {
  596. return false
  597. }
  598. }
  599. }
  600. if f.Ret != nil {
  601. return g.isSupported(f.Ret)
  602. }
  603. return true
  604. }
  605. func (g *ObjcWrapper) isErrorType(t *objc.Type) bool {
  606. // Must be a NSError ** type
  607. return t.Kind == objc.Class && t.Indirect && t.Name == "NSError"
  608. }
  609. func (g *ObjcWrapper) isSupported(t *objc.Type) bool {
  610. if t.Indirect {
  611. return false
  612. }
  613. switch t.Kind {
  614. case objc.Unknown:
  615. return false
  616. case objc.Protocol:
  617. // TODO: support inout parameters.
  618. return !strings.HasSuffix(t.Decl, " *")
  619. case objc.Class:
  620. return t.Name != "SEL" && t.Name != "void"
  621. default:
  622. return true
  623. }
  624. }
  625. func (g *ObjcWrapper) cgoType(t *objc.Type) string {
  626. switch t.Kind {
  627. case objc.Uint:
  628. return "C.ulong"
  629. case objc.Ushort:
  630. return "C.ushort"
  631. case objc.Uchar:
  632. return "C.uchar"
  633. default:
  634. return "C." + g.cType(t)
  635. }
  636. }
  637. func (g *ObjcWrapper) cType(t *objc.Type) string {
  638. switch t.Kind {
  639. case objc.Protocol, objc.Class:
  640. return "int"
  641. case objc.String:
  642. return "nstring"
  643. case objc.Data:
  644. return "nbyteslice"
  645. case objc.Int:
  646. return "long"
  647. case objc.Uint:
  648. return "unsigned long"
  649. case objc.Short:
  650. return "short"
  651. case objc.Ushort:
  652. return "unsigned short"
  653. case objc.Bool:
  654. return "char"
  655. case objc.Char:
  656. return "char"
  657. case objc.Uchar:
  658. return "unsigned char"
  659. case objc.Float:
  660. return "float"
  661. case objc.Double:
  662. return "double"
  663. default:
  664. panic("invalid kind")
  665. }
  666. }
  667. func (g *ObjcWrapper) objcType(t *objc.Type) string {
  668. return t.Decl
  669. }
  670. func (g *ObjcWrapper) lookupImported(t *objc.Type) *objc.Named {
  671. var mangled string
  672. switch t.Kind {
  673. case objc.Class:
  674. mangled = t.Name + "C"
  675. case objc.Protocol:
  676. mangled = t.Name + "P"
  677. default:
  678. panic("invalid type kind")
  679. }
  680. if n, exists := g.imported[mangled]; exists {
  681. return n
  682. }
  683. return g.imported[t.Name]
  684. }
  685. func (g *ObjcWrapper) goType(t *objc.Type, local bool) string {
  686. switch t.Kind {
  687. case objc.String:
  688. return "string"
  689. case objc.Data:
  690. return "[]byte"
  691. case objc.Int:
  692. return "int"
  693. case objc.Uint:
  694. return "uint"
  695. case objc.Short:
  696. return "int16"
  697. case objc.Ushort:
  698. return "uint16"
  699. case objc.Bool:
  700. return "bool"
  701. case objc.Char:
  702. return "byte"
  703. case objc.Uchar:
  704. return "uint8"
  705. case objc.Float:
  706. return "float32"
  707. case objc.Double:
  708. return "float64"
  709. case objc.Protocol, objc.Class:
  710. var n *objc.Named
  711. n = g.lookupImported(t)
  712. name := n.Module + "_" + n.GoName
  713. if !local {
  714. name = "ObjC." + name
  715. }
  716. return name
  717. default:
  718. panic("invalid kind")
  719. }
  720. }