genclasses.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948
  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. "fmt"
  7. "path"
  8. "reflect"
  9. "strings"
  10. "unicode"
  11. "unicode/utf8"
  12. "golang.org/x/mobile/internal/importers"
  13. "golang.org/x/mobile/internal/importers/java"
  14. )
  15. type (
  16. // ClassGen generates Go and C stubs for Java classes so import statements
  17. // on the form
  18. //
  19. //
  20. // import "Java/classpath/to/Class"
  21. //
  22. // will work.
  23. ClassGen struct {
  24. *Printer
  25. // JavaPkg is the Java package prefix for the generated classes. The prefix is prepended to the Go
  26. // package name to create the full Java package name.
  27. JavaPkg string
  28. imported map[string]struct{}
  29. // The list of imported Java classes
  30. classes []*java.Class
  31. // The list of Go package paths with Java interfaces inside
  32. jpkgs []string
  33. // For each Go package path, the list of Java classes.
  34. typePkgs map[string][]*java.Class
  35. // For each Go package path, the Java class with static functions
  36. // or constants.
  37. clsPkgs map[string]*java.Class
  38. // goClsMap is the map of Java class names to Go type names, qualified with package name. Go types
  39. // that implement Java classes need Super methods and Unwrap methods.
  40. goClsMap map[string]string
  41. // goClsImports is the list of imports of user packages that contains the Go types implementing Java
  42. // classes.
  43. goClsImports []string
  44. }
  45. )
  46. func (g *ClassGen) isSupported(t *java.Type) bool {
  47. switch t.Kind {
  48. case java.Array:
  49. // TODO: Support all array types
  50. return t.Elem.Kind == java.Byte
  51. default:
  52. return true
  53. }
  54. }
  55. func (g *ClassGen) isFuncSetSupported(fs *java.FuncSet) bool {
  56. for _, f := range fs.Funcs {
  57. if g.isFuncSupported(f) {
  58. return true
  59. }
  60. }
  61. return false
  62. }
  63. func (g *ClassGen) isFuncSupported(f *java.Func) bool {
  64. for _, a := range f.Params {
  65. if !g.isSupported(a) {
  66. return false
  67. }
  68. }
  69. if f.Ret != nil {
  70. return g.isSupported(f.Ret)
  71. }
  72. return true
  73. }
  74. func (g *ClassGen) goType(t *java.Type, local bool) string {
  75. if t == nil {
  76. // interface{} is used for parameters types for overloaded methods
  77. // where no common ancestor type exists.
  78. return "interface{}"
  79. }
  80. switch t.Kind {
  81. case java.Int:
  82. return "int32"
  83. case java.Boolean:
  84. return "bool"
  85. case java.Short:
  86. return "int16"
  87. case java.Char:
  88. return "uint16"
  89. case java.Byte:
  90. return "byte"
  91. case java.Long:
  92. return "int64"
  93. case java.Float:
  94. return "float32"
  95. case java.Double:
  96. return "float64"
  97. case java.String:
  98. return "string"
  99. case java.Array:
  100. return "[]" + g.goType(t.Elem, local)
  101. case java.Object:
  102. name := goClsName(t.Class)
  103. if !local {
  104. name = "Java." + name
  105. }
  106. return name
  107. default:
  108. panic("invalid kind")
  109. }
  110. }
  111. // Init initializes the class wrapper generator. Classes is the
  112. // list of classes to wrap, goClasses is the list of Java classes
  113. // implemented in Go.
  114. func (g *ClassGen) Init(classes []*java.Class, goClasses []importers.Struct) {
  115. g.goClsMap = make(map[string]string)
  116. impMap := make(map[string]struct{})
  117. for _, s := range goClasses {
  118. n := s.Pkg + "." + s.Name
  119. jn := n
  120. if g.JavaPkg != "" {
  121. jn = g.JavaPkg + "." + jn
  122. }
  123. g.goClsMap[jn] = n
  124. if _, exists := impMap[s.PkgPath]; !exists {
  125. impMap[s.PkgPath] = struct{}{}
  126. g.goClsImports = append(g.goClsImports, s.PkgPath)
  127. }
  128. }
  129. g.classes = classes
  130. g.imported = make(map[string]struct{})
  131. g.typePkgs = make(map[string][]*java.Class)
  132. g.clsPkgs = make(map[string]*java.Class)
  133. pkgSet := make(map[string]struct{})
  134. for _, cls := range classes {
  135. g.imported[cls.Name] = struct{}{}
  136. clsPkg := strings.Replace(cls.Name, ".", "/", -1)
  137. g.clsPkgs[clsPkg] = cls
  138. typePkg := path.Dir(clsPkg)
  139. g.typePkgs[typePkg] = append(g.typePkgs[typePkg], cls)
  140. if _, exists := pkgSet[clsPkg]; !exists {
  141. pkgSet[clsPkg] = struct{}{}
  142. g.jpkgs = append(g.jpkgs, clsPkg)
  143. }
  144. if _, exists := pkgSet[typePkg]; !exists {
  145. pkgSet[typePkg] = struct{}{}
  146. g.jpkgs = append(g.jpkgs, typePkg)
  147. }
  148. }
  149. }
  150. // Packages return the list of Go packages to be generated.
  151. func (g *ClassGen) Packages() []string {
  152. return g.jpkgs
  153. }
  154. func (g *ClassGen) GenPackage(idx int) {
  155. jpkg := g.jpkgs[idx]
  156. g.Printf(gobindPreamble)
  157. g.Printf("package %s\n\n", path.Base(jpkg))
  158. g.Printf("import \"Java\"\n\n")
  159. g.Printf("const _ = Java.Dummy\n\n")
  160. for _, cls := range g.typePkgs[jpkg] {
  161. g.Printf("type %s Java.%s\n", cls.PkgName, goClsName(cls.Name))
  162. }
  163. if cls, ok := g.clsPkgs[jpkg]; ok {
  164. g.Printf("const (\n")
  165. g.Indent()
  166. // Constants
  167. for _, v := range cls.Vars {
  168. if g.isSupported(v.Type) && v.Constant() {
  169. g.Printf("%s = %s\n", initialUpper(v.Name), v.Val)
  170. }
  171. }
  172. g.Outdent()
  173. g.Printf(")\n\n")
  174. g.Printf("var (\n")
  175. g.Indent()
  176. // Functions
  177. loop:
  178. for _, fs := range cls.Funcs {
  179. for _, f := range fs.Funcs {
  180. if f.Public && g.isFuncSupported(f) {
  181. g.Printf("%s func", fs.GoName)
  182. g.genFuncDecl(false, fs)
  183. g.Printf("\n")
  184. continue loop
  185. }
  186. }
  187. }
  188. g.Printf("// Cast takes a proxy for a Java object and converts it to a %s proxy.\n", cls.Name)
  189. g.Printf("// Cast panics if the argument is not a proxy or if the underlying object does\n")
  190. g.Printf("// not extend or implement %s.\n", cls.Name)
  191. g.Printf("Cast func(v interface{}) Java.%s\n", goClsName(cls.Name))
  192. g.Outdent()
  193. g.Printf(")\n\n")
  194. }
  195. }
  196. func (g *ClassGen) GenGo() {
  197. g.Printf(classesGoHeader)
  198. for _, cls := range g.classes {
  199. pkgName := strings.Replace(cls.Name, ".", "/", -1)
  200. g.Printf("import %q\n", "Java/"+pkgName)
  201. }
  202. for _, imp := range g.goClsImports {
  203. g.Printf("import %q\n", imp)
  204. }
  205. if len(g.classes) > 0 {
  206. g.Printf("import \"unsafe\"\n\n")
  207. g.Printf("import \"reflect\"\n\n")
  208. g.Printf("import \"fmt\"\n\n")
  209. }
  210. g.Printf("type proxy interface { Bind_proxy_refnum__() int32 }\n\n")
  211. g.Printf("// Suppress unused package error\n\n")
  212. g.Printf("var _ = _seq.FromRefNum\n")
  213. g.Printf("const _ = Java.Dummy\n\n")
  214. g.Printf("//export initClasses\n")
  215. g.Printf("func initClasses() {\n")
  216. g.Indent()
  217. g.Printf("C.init_proxies()\n")
  218. for _, cls := range g.classes {
  219. g.Printf("init_%s()\n", cls.JNIName)
  220. }
  221. g.Outdent()
  222. g.Printf("}\n\n")
  223. for _, cls := range g.classes {
  224. g.genGo(cls)
  225. }
  226. }
  227. func (g *ClassGen) GenH() {
  228. g.Printf(classesHHeader)
  229. for _, tn := range []string{"jint", "jboolean", "jshort", "jchar", "jbyte", "jlong", "jfloat", "jdouble", "nstring", "nbyteslice"} {
  230. g.Printf("typedef struct ret_%s {\n", tn)
  231. g.Printf(" %s res;\n", tn)
  232. g.Printf(" jint exc;\n")
  233. g.Printf("} ret_%s;\n", tn)
  234. }
  235. g.Printf("\n")
  236. for _, cls := range g.classes {
  237. for _, fs := range cls.AllMethods {
  238. for _, f := range fs.Funcs {
  239. if !g.isFuncSupported(f) {
  240. continue
  241. }
  242. g.Printf("extern ")
  243. g.genCMethodDecl("cproxy", cls.JNIName, f)
  244. g.Printf(";\n")
  245. if _, ok := g.goClsMap[cls.Name]; ok {
  246. g.Printf("extern ")
  247. g.genCMethodDecl("csuper", cls.JNIName, f)
  248. g.Printf(";\n")
  249. }
  250. }
  251. }
  252. }
  253. for _, cls := range g.classes {
  254. g.genH(cls)
  255. }
  256. }
  257. func (g *ClassGen) GenC() {
  258. g.Printf(classesCHeader)
  259. for _, cls := range g.classes {
  260. g.Printf("static jclass class_%s;\n", cls.JNIName)
  261. if _, ok := g.goClsMap[cls.Name]; ok {
  262. g.Printf("static jclass sclass_%s;\n", cls.JNIName)
  263. }
  264. for _, fs := range cls.Funcs {
  265. for _, f := range fs.Funcs {
  266. if !f.Public || !g.isFuncSupported(f) {
  267. continue
  268. }
  269. g.Printf("static jmethodID m_s_%s_%s;\n", cls.JNIName, f.JNIName)
  270. }
  271. }
  272. for _, fs := range cls.AllMethods {
  273. for _, f := range fs.Funcs {
  274. if g.isFuncSupported(f) {
  275. g.Printf("static jmethodID m_%s_%s;\n", cls.JNIName, f.JNIName)
  276. if _, ok := g.goClsMap[cls.Name]; ok {
  277. g.Printf("static jmethodID sm_%s_%s;\n", cls.JNIName, f.JNIName)
  278. }
  279. }
  280. }
  281. }
  282. g.genC(cls)
  283. }
  284. g.Printf("\n")
  285. g.Printf("void init_proxies() {\n")
  286. g.Indent()
  287. g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", len(g.classes))
  288. g.Printf("jclass clazz;\n")
  289. for _, cls := range g.classes {
  290. g.Printf("clazz = go_seq_find_class(%q);\n", strings.Replace(cls.FindName, ".", "/", -1))
  291. g.Printf("if (clazz != NULL) {\n")
  292. g.Indent()
  293. g.Printf("class_%s = (*env)->NewGlobalRef(env, clazz);\n", cls.JNIName)
  294. if _, ok := g.goClsMap[cls.Name]; ok {
  295. g.Printf("sclass_%s = (*env)->GetSuperclass(env, clazz);\n", cls.JNIName)
  296. g.Printf("sclass_%s = (*env)->NewGlobalRef(env, sclass_%s);\n", cls.JNIName, cls.JNIName)
  297. }
  298. for _, fs := range cls.Funcs {
  299. for _, f := range fs.Funcs {
  300. if !f.Public || !g.isFuncSupported(f) {
  301. continue
  302. }
  303. g.Printf("m_s_%s_%s = ", cls.JNIName, f.JNIName)
  304. if f.Constructor {
  305. g.Printf("go_seq_get_method_id(clazz, \"<init>\", %q);\n", f.Desc)
  306. } else {
  307. g.Printf("go_seq_get_static_method_id(clazz, %q, %q);\n", f.Name, f.Desc)
  308. }
  309. }
  310. }
  311. for _, fs := range cls.AllMethods {
  312. for _, f := range fs.Funcs {
  313. if g.isFuncSupported(f) {
  314. g.Printf("m_%s_%s = go_seq_get_method_id(clazz, %q, %q);\n", cls.JNIName, f.JNIName, f.Name, f.Desc)
  315. if _, ok := g.goClsMap[cls.Name]; ok {
  316. g.Printf("sm_%s_%s = go_seq_get_method_id(sclass_%s, %q, %q);\n", cls.JNIName, f.JNIName, cls.JNIName, f.Name, f.Desc)
  317. }
  318. }
  319. }
  320. }
  321. g.Outdent()
  322. g.Printf("}\n")
  323. }
  324. g.Printf("go_seq_pop_local_frame(env);\n")
  325. g.Outdent()
  326. g.Printf("}\n\n")
  327. for _, cls := range g.classes {
  328. for _, fs := range cls.AllMethods {
  329. for _, f := range fs.Funcs {
  330. if !g.isFuncSupported(f) {
  331. continue
  332. }
  333. g.genCMethodDecl("cproxy", cls.JNIName, f)
  334. g.genCMethodBody(cls, f, false)
  335. if _, ok := g.goClsMap[cls.Name]; ok {
  336. g.genCMethodDecl("csuper", cls.JNIName, f)
  337. g.genCMethodBody(cls, f, true)
  338. }
  339. }
  340. }
  341. }
  342. }
  343. func (g *ClassGen) GenInterfaces() {
  344. g.Printf(classesPkgHeader)
  345. for _, cls := range g.classes {
  346. g.genInterface(cls)
  347. }
  348. }
  349. func (g *ClassGen) genCMethodBody(cls *java.Class, f *java.Func, virtual bool) {
  350. g.Printf(" {\n")
  351. g.Indent()
  352. // Add 1 for the 'this' argument
  353. g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", len(f.Params)+1)
  354. g.Printf("// Must be a Java object\n")
  355. g.Printf("jobject _this = go_seq_from_refnum(env, this, NULL, NULL);\n")
  356. for i, a := range f.Params {
  357. g.genCToJava(fmt.Sprintf("a%d", i), a)
  358. }
  359. if f.Ret != nil {
  360. g.Printf("%s res = ", f.Ret.JNIType())
  361. }
  362. g.Printf("(*env)->Call")
  363. if virtual {
  364. g.Printf("Nonvirtual")
  365. }
  366. if f.Ret != nil {
  367. g.Printf("%s", f.Ret.JNICallType())
  368. } else {
  369. g.Printf("Void")
  370. }
  371. g.Printf("Method(env, _this, ")
  372. if virtual {
  373. g.Printf("sclass_%s, sm_%s_%s", cls.JNIName, cls.JNIName, f.JNIName)
  374. } else {
  375. g.Printf("m_%s_%s", cls.JNIName, f.JNIName)
  376. }
  377. for i := range f.Params {
  378. g.Printf(", _a%d", i)
  379. }
  380. g.Printf(");\n")
  381. g.Printf("jobject _exc = go_seq_get_exception(env);\n")
  382. g.Printf("int32_t _exc_ref = go_seq_to_refnum(env, _exc);\n")
  383. if f.Ret != nil {
  384. g.genCRetClear("res", f.Ret, "_exc")
  385. g.genJavaToC("res", f.Ret)
  386. }
  387. g.Printf("go_seq_pop_local_frame(env);\n")
  388. if f.Ret != nil {
  389. g.Printf("ret_%s __res = {_res, _exc_ref};\n", f.Ret.CType())
  390. g.Printf("return __res;\n")
  391. } else {
  392. g.Printf("return _exc_ref;\n")
  393. }
  394. g.Outdent()
  395. g.Printf("}\n\n")
  396. }
  397. func initialUpper(s string) string {
  398. if s == "" {
  399. return ""
  400. }
  401. r, n := utf8.DecodeRuneInString(s)
  402. return string(unicode.ToUpper(r)) + s[n:]
  403. }
  404. func (g *ClassGen) genFuncDecl(local bool, fs *java.FuncSet) {
  405. g.Printf("(")
  406. for i, a := range fs.Params {
  407. if i > 0 {
  408. g.Printf(", ")
  409. }
  410. g.Printf("a%d ", i)
  411. if i == len(fs.Params)-1 && fs.Variadic {
  412. g.Printf("...")
  413. }
  414. g.Printf("%s", g.goType(a, local))
  415. }
  416. g.Printf(")")
  417. if fs.Throws {
  418. if fs.HasRet {
  419. g.Printf(" (%s, error)", g.goType(fs.Ret, local))
  420. } else {
  421. g.Printf(" error")
  422. }
  423. } else if fs.HasRet {
  424. g.Printf(" %s", g.goType(fs.Ret, local))
  425. }
  426. }
  427. func (g *ClassGen) genC(cls *java.Class) {
  428. for _, fs := range cls.Funcs {
  429. for _, f := range fs.Funcs {
  430. if !f.Public || !g.isFuncSupported(f) {
  431. continue
  432. }
  433. g.genCFuncDecl(cls.JNIName, f)
  434. g.Printf(" {\n")
  435. g.Indent()
  436. g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", len(f.Params))
  437. for i, a := range f.Params {
  438. g.genCToJava(fmt.Sprintf("a%d", i), a)
  439. }
  440. if f.Constructor {
  441. g.Printf("jobject res = (*env)->NewObject(env")
  442. } else if f.Ret != nil {
  443. g.Printf("%s res = (*env)->CallStatic%sMethod(env", f.Ret.JNIType(), f.Ret.JNICallType())
  444. } else {
  445. g.Printf("(*env)->CallStaticVoidMethod(env")
  446. }
  447. g.Printf(", class_%s, m_s_%s_%s", cls.JNIName, cls.JNIName, f.JNIName)
  448. for i := range f.Params {
  449. g.Printf(", _a%d", i)
  450. }
  451. g.Printf(");\n")
  452. g.Printf("jobject _exc = go_seq_get_exception(env);\n")
  453. g.Printf("int32_t _exc_ref = go_seq_to_refnum(env, _exc);\n")
  454. if f.Ret != nil {
  455. g.genCRetClear("res", f.Ret, "_exc")
  456. g.genJavaToC("res", f.Ret)
  457. }
  458. g.Printf("go_seq_pop_local_frame(env);\n")
  459. if f.Ret != nil {
  460. g.Printf("ret_%s __res = {_res, _exc_ref};\n", f.Ret.CType())
  461. g.Printf("return __res;\n")
  462. } else {
  463. g.Printf("return _exc_ref;\n")
  464. }
  465. g.Outdent()
  466. g.Printf("}\n\n")
  467. }
  468. }
  469. }
  470. func (g *ClassGen) genH(cls *java.Class) {
  471. for _, fs := range cls.Funcs {
  472. for _, f := range fs.Funcs {
  473. if !f.Public || !g.isFuncSupported(f) {
  474. continue
  475. }
  476. g.Printf("extern ")
  477. g.genCFuncDecl(cls.JNIName, f)
  478. g.Printf(";\n")
  479. }
  480. }
  481. }
  482. func (g *ClassGen) genCMethodDecl(prefix, jniName string, f *java.Func) {
  483. if f.Ret != nil {
  484. g.Printf("ret_%s", f.Ret.CType())
  485. } else {
  486. // Return only the exception, if any
  487. g.Printf("jint")
  488. }
  489. g.Printf(" %s_%s_%s(jint this", prefix, jniName, f.JNIName)
  490. for i, a := range f.Params {
  491. g.Printf(", %s a%d", a.CType(), i)
  492. }
  493. g.Printf(")")
  494. }
  495. func (g *ClassGen) genCFuncDecl(jniName string, f *java.Func) {
  496. if f.Ret != nil {
  497. g.Printf("ret_%s", f.Ret.CType())
  498. } else {
  499. // Return only the exception, if any
  500. g.Printf("jint")
  501. }
  502. g.Printf(" cproxy_s_%s_%s(", jniName, f.JNIName)
  503. for i, a := range f.Params {
  504. if i > 0 {
  505. g.Printf(", ")
  506. }
  507. g.Printf("%s a%d", a.CType(), i)
  508. }
  509. g.Printf(")")
  510. }
  511. func (g *ClassGen) genGo(cls *java.Class) {
  512. g.Printf("var class_%s C.jclass\n\n", cls.JNIName)
  513. g.Printf("func init_%s() {\n", cls.JNIName)
  514. g.Indent()
  515. g.Printf("cls := C.CString(%q)\n", strings.Replace(cls.FindName, ".", "/", -1))
  516. g.Printf("clazz := C.go_seq_find_class(cls)\n")
  517. g.Printf("C.free(unsafe.Pointer(cls))\n")
  518. // Before Go 1.11 clazz was a pointer value, an uintptr after.
  519. g.Printf("if uintptr(clazz) == 0 {\n")
  520. g.Printf(" return\n")
  521. g.Printf("}\n")
  522. g.Printf("class_%s = clazz\n", cls.JNIName)
  523. for _, fs := range cls.Funcs {
  524. var supported bool
  525. for _, f := range fs.Funcs {
  526. if f.Public && g.isFuncSupported(f) {
  527. supported = true
  528. break
  529. }
  530. }
  531. if !supported {
  532. continue
  533. }
  534. g.Printf("%s.%s = func", cls.PkgName, fs.GoName)
  535. g.genFuncDecl(false, fs)
  536. g.genFuncBody(cls, fs, "cproxy_s", true)
  537. }
  538. g.Printf("%s.Cast = func(v interface{}) Java.%s {\n", cls.PkgName, goClsName(cls.Name))
  539. g.Indent()
  540. g.Printf("t := reflect.TypeOf((*proxy_class_%s)(nil))\n", cls.JNIName)
  541. g.Printf("cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_%s)\n", cls.JNIName)
  542. g.Printf("ref := C.jint(_seq.ToRefNum(cv))\n")
  543. g.Printf("if C.go_seq_isinstanceof(ref, class_%s) != 1 {\n", cls.JNIName)
  544. g.Printf(" panic(fmt.Errorf(\"%%T is not an instance of %%s\", v, %q))\n", cls.Name)
  545. g.Printf("}\n")
  546. g.Printf("return cv\n")
  547. g.Outdent()
  548. g.Printf("}\n")
  549. g.Outdent()
  550. g.Printf("}\n\n")
  551. g.Printf("type proxy_class_%s _seq.Ref\n\n", cls.JNIName)
  552. g.Printf("func (p *proxy_class_%s) Bind_proxy_refnum__() int32 {\n", cls.JNIName)
  553. g.Indent()
  554. g.Printf("return (*_seq.Ref)(p).Bind_IncNum()\n")
  555. g.Outdent()
  556. g.Printf("}\n\n")
  557. for _, fs := range cls.AllMethods {
  558. if !g.isFuncSetSupported(fs) {
  559. continue
  560. }
  561. g.Printf("func (p *proxy_class_%s) %s", cls.JNIName, fs.GoName)
  562. g.genFuncDecl(false, fs)
  563. g.genFuncBody(cls, fs, "cproxy", false)
  564. }
  565. if cls.Throwable {
  566. g.Printf("func (p *proxy_class_%s) Error() string {\n", cls.JNIName)
  567. g.Printf(" return p.ToString()\n")
  568. g.Printf("}\n")
  569. }
  570. if goName, ok := g.goClsMap[cls.Name]; ok {
  571. g.Printf("func (p *proxy_class_%s) Super() Java.%s {\n", cls.JNIName, goClsName(cls.Name))
  572. g.Printf(" return &super_%s{p}\n", cls.JNIName)
  573. g.Printf("}\n\n")
  574. g.Printf("type super_%s struct {*proxy_class_%[1]s}\n\n", cls.JNIName)
  575. g.Printf("func (p *proxy_class_%s) Unwrap() interface{} {\n", cls.JNIName)
  576. g.Indent()
  577. g.Printf("goRefnum := C.go_seq_unwrap(C.jint(p.Bind_proxy_refnum__()))\n")
  578. g.Printf("return _seq.FromRefNum(int32(goRefnum)).Get().(*%s)\n", goName)
  579. g.Outdent()
  580. g.Printf("}\n\n")
  581. for _, fs := range cls.AllMethods {
  582. if !g.isFuncSetSupported(fs) {
  583. continue
  584. }
  585. g.Printf("func (p *super_%s) %s", cls.JNIName, fs.GoName)
  586. g.genFuncDecl(false, fs)
  587. g.genFuncBody(cls, fs, "csuper", false)
  588. }
  589. }
  590. }
  591. // genFuncBody generated a Go function body for a FuncSet. It resolves overloading dynamically,
  592. // by inspecting the number of arguments (if the FuncSet contains varying parameter counts),
  593. // and their types.
  594. func (g *ClassGen) genFuncBody(cls *java.Class, fs *java.FuncSet, prefix string, static bool) {
  595. maxp := len(fs.Funcs[0].Params)
  596. minp := maxp
  597. // sort the function variants into argument sizes.
  598. buckets := make(map[int][]*java.Func)
  599. numF := 0
  600. for _, f := range fs.Funcs {
  601. if !g.isFuncSupported(f) {
  602. continue
  603. }
  604. numF++
  605. n := len(f.Params)
  606. if n < minp {
  607. minp = n
  608. } else if n > maxp {
  609. maxp = n
  610. }
  611. buckets[n] = append(buckets[n], f)
  612. }
  613. g.Printf(" {\n")
  614. g.Indent()
  615. if len(buckets) != 1 {
  616. // Switch over the number of arguments.
  617. g.Printf("switch %d + len(a%d) {\n", minp, minp)
  618. }
  619. for i := minp; i <= maxp; i++ {
  620. funcs := buckets[i]
  621. if len(funcs) == 0 {
  622. continue
  623. }
  624. if len(buckets) != 1 {
  625. g.Printf("case %d:\n", i)
  626. g.Indent()
  627. }
  628. for _, f := range funcs {
  629. if len(funcs) > 1 {
  630. g.Printf("{\n")
  631. g.Indent()
  632. }
  633. var argNames []string
  634. var preds []string
  635. for i, a := range f.Params {
  636. var ct *java.Type
  637. var argName string
  638. if i >= minp {
  639. argName = fmt.Sprintf("a%d[%d]", minp, i-minp)
  640. ct = fs.Params[minp]
  641. } else {
  642. argName = fmt.Sprintf("a%d", i)
  643. ct = fs.Params[i]
  644. }
  645. if !reflect.DeepEqual(ct, a) {
  646. g.Printf("_a%d, ok%d := %s.(%s)\n", i, i, argName, g.goType(a, false))
  647. argName = fmt.Sprintf("_a%d", i)
  648. preds = append(preds, fmt.Sprintf("ok%d", i))
  649. }
  650. argNames = append(argNames, argName)
  651. }
  652. if len(preds) > 0 {
  653. g.Printf("if %s {\n", strings.Join(preds, " && "))
  654. g.Indent()
  655. }
  656. for i, a := range f.Params {
  657. g.genWrite(fmt.Sprintf("__a%d", i), argNames[i], a, modeTransient)
  658. }
  659. g.Printf("res := C.%s_%s_%s(", prefix, cls.JNIName, f.JNIName)
  660. if !static {
  661. g.Printf("C.jint(p.Bind_proxy_refnum__())")
  662. }
  663. for i := range f.Params {
  664. if !static || i > 0 {
  665. g.Printf(", ")
  666. }
  667. g.Printf("__a%d", i)
  668. }
  669. g.Printf(")\n")
  670. g.genFuncRet(fs, f, numF > 1)
  671. if len(preds) > 0 {
  672. g.Outdent()
  673. g.Printf("}\n")
  674. }
  675. if len(funcs) > 1 {
  676. g.Outdent()
  677. g.Printf("}\n")
  678. }
  679. }
  680. if len(buckets) != 1 {
  681. g.Outdent()
  682. }
  683. }
  684. if len(buckets) != 1 {
  685. g.Printf("}\n")
  686. }
  687. if numF > 1 {
  688. g.Printf("panic(\"no overloaded method found for %s.%s that matched the arguments\")\n", cls.Name, fs.Name)
  689. }
  690. g.Outdent()
  691. g.Printf("}\n\n")
  692. }
  693. func (g *ClassGen) genFuncRet(fs *java.FuncSet, f *java.Func, mustReturn bool) {
  694. if f.Ret != nil {
  695. g.genRead("_res", "res.res", f.Ret, modeRetained)
  696. g.genRefRead("_exc", "res.exc", "error", "proxy_error", true)
  697. } else {
  698. g.genRefRead("_exc", "res", "error", "proxy_error", true)
  699. }
  700. if !fs.Throws {
  701. g.Printf("if (_exc != nil) { panic(_exc) }\n")
  702. if fs.HasRet {
  703. if f.Ret != nil {
  704. g.Printf("return _res\n")
  705. } else {
  706. // The variant doesn't return a value, but the common
  707. // signature does. Use nil as a placeholder return value.
  708. g.Printf("return nil\n")
  709. }
  710. } else if mustReturn {
  711. // If there are overloaded variants, return here to avoid the fallback
  712. // panic generated in genFuncBody.
  713. g.Printf("return\n")
  714. }
  715. } else {
  716. if fs.HasRet {
  717. if f.Ret != nil {
  718. g.Printf("return _res, _exc\n")
  719. } else {
  720. // As above, use a nil placeholder return value.
  721. g.Printf("return nil, _exc\n")
  722. }
  723. } else {
  724. g.Printf("return _exc\n")
  725. }
  726. }
  727. }
  728. func (g *ClassGen) genRead(to, from string, t *java.Type, mode varMode) {
  729. switch t.Kind {
  730. case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double:
  731. g.Printf("%s := %s(%s)\n", to, g.goType(t, false), from)
  732. case java.Boolean:
  733. g.Printf("%s := %s != C.JNI_FALSE\n", to, from)
  734. case java.String:
  735. g.Printf("%s := decodeString(%s)\n", to, from)
  736. case java.Array:
  737. if t.Elem.Kind != java.Byte {
  738. panic("unsupported array type")
  739. }
  740. g.Printf("%s := toSlice(%s, %v)\n", to, from, mode == modeRetained)
  741. case java.Object:
  742. _, hasProxy := g.imported[t.Class]
  743. g.genRefRead(to, from, g.goType(t, false), "proxy_class_"+flattenName(t.Class), hasProxy)
  744. default:
  745. panic("invalid kind")
  746. }
  747. }
  748. func (g *ClassGen) genRefRead(to, from string, intfName, proxyName string, hasProxy bool) {
  749. g.Printf("var %s %s\n", to, intfName)
  750. g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", to, from)
  751. g.Printf("if %s_ref != nil {\n", to)
  752. g.Printf(" if %s < 0 { // go object\n", from)
  753. g.Printf(" %s = %s_ref.Get().(%s)\n", to, to, intfName)
  754. g.Printf(" } else { // foreign object\n")
  755. if hasProxy {
  756. g.Printf(" %s = (*%s)(%s_ref)\n", to, proxyName, to)
  757. } else {
  758. g.Printf(" %s = %s_ref\n", to, to)
  759. }
  760. g.Printf(" }\n")
  761. g.Printf("}\n")
  762. }
  763. func (g *ClassGen) genWrite(dst, v string, t *java.Type, mode varMode) {
  764. switch t.Kind {
  765. case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double:
  766. g.Printf("%s := C.%s(%s)\n", dst, t.CType(), v)
  767. case java.Boolean:
  768. g.Printf("%s := C.jboolean(C.JNI_FALSE)\n", dst)
  769. g.Printf("if %s {\n", v)
  770. g.Printf(" %s = C.jboolean(C.JNI_TRUE)\n", dst)
  771. g.Printf("}\n")
  772. case java.String:
  773. g.Printf("%s := encodeString(%s)\n", dst, v)
  774. case java.Array:
  775. if t.Elem.Kind != java.Byte {
  776. panic("unsupported array type")
  777. }
  778. g.Printf("%s := fromSlice(%s, %v)\n", dst, v, mode == modeRetained)
  779. case java.Object:
  780. g.Printf("var %s C.jint = _seq.NullRefNum\n", dst)
  781. g.Printf("if %s != nil {\n", v)
  782. g.Printf(" %s = C.jint(_seq.ToRefNum(%s))\n", dst, v)
  783. g.Printf("}\n")
  784. default:
  785. panic("invalid kind")
  786. }
  787. }
  788. // genCRetClear clears the result value from a JNI call if an exception was
  789. // raised.
  790. func (g *ClassGen) genCRetClear(v string, t *java.Type, exc string) {
  791. g.Printf("if (%s != NULL) {\n", exc)
  792. g.Indent()
  793. switch t.Kind {
  794. case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double, java.Boolean:
  795. g.Printf("%s = 0;\n", v)
  796. default:
  797. // Assume a nullable type. It will break if we missed a type.
  798. g.Printf("%s = NULL;\n", v)
  799. }
  800. g.Outdent()
  801. g.Printf("}\n")
  802. }
  803. func (g *ClassGen) genJavaToC(v string, t *java.Type) {
  804. switch t.Kind {
  805. case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double, java.Boolean:
  806. g.Printf("%s _%s = %s;\n", t.JNIType(), v, v)
  807. case java.String:
  808. g.Printf("nstring _%s = go_seq_from_java_string(env, %s);\n", v, v)
  809. case java.Array:
  810. if t.Elem.Kind != java.Byte {
  811. panic("unsupported array type")
  812. }
  813. g.Printf("nbyteslice _%s = go_seq_from_java_bytearray(env, %s, 1);\n", v, v)
  814. case java.Object:
  815. g.Printf("jint _%s = go_seq_to_refnum(env, %s);\n", v, v)
  816. default:
  817. panic("invalid kind")
  818. }
  819. }
  820. func (g *ClassGen) genCToJava(v string, t *java.Type) {
  821. switch t.Kind {
  822. case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double, java.Boolean:
  823. g.Printf("%s _%s = %s;\n", t.JNIType(), v, v)
  824. case java.String:
  825. g.Printf("jstring _%s = go_seq_to_java_string(env, %s);\n", v, v)
  826. case java.Array:
  827. if t.Elem.Kind != java.Byte {
  828. panic("unsupported array type")
  829. }
  830. g.Printf("jbyteArray _%s = go_seq_to_java_bytearray(env, %s, 0);\n", v, v)
  831. case java.Object:
  832. g.Printf("jobject _%s = go_seq_from_refnum(env, %s, NULL, NULL);\n", v, v)
  833. default:
  834. panic("invalid kind")
  835. }
  836. }
  837. func goClsName(n string) string {
  838. return initialUpper(strings.Replace(n, ".", "_", -1))
  839. }
  840. func (g *ClassGen) genInterface(cls *java.Class) {
  841. g.Printf("type %s interface {\n", goClsName(cls.Name))
  842. g.Indent()
  843. // Methods
  844. for _, fs := range cls.AllMethods {
  845. if !g.isFuncSetSupported(fs) {
  846. continue
  847. }
  848. g.Printf("%s", fs.GoName)
  849. g.genFuncDecl(true, fs)
  850. g.Printf("\n")
  851. }
  852. if goName, ok := g.goClsMap[cls.Name]; ok {
  853. g.Printf("Super() %s\n", goClsName(cls.Name))
  854. g.Printf("// Unwrap returns the Go object this Java instance\n")
  855. g.Printf("// is wrapping.\n")
  856. g.Printf("// The return value is a %s, but the delclared type is\n", goName)
  857. g.Printf("// interface{} to avoid import cycles.\n")
  858. g.Printf("Unwrap() interface{}\n")
  859. }
  860. if cls.Throwable {
  861. g.Printf("Error() string\n")
  862. }
  863. g.Outdent()
  864. g.Printf("}\n\n")
  865. }
  866. // Flatten java class names. "java.package.Class$Inner" is converted to
  867. // "java_package_Class_Inner"
  868. func flattenName(n string) string {
  869. return strings.Replace(strings.Replace(n, ".", "_", -1), "$", "_", -1)
  870. }
  871. const (
  872. classesPkgHeader = gobindPreamble + `
  873. package Java
  874. // Used to silence this package not used errors
  875. const Dummy = 0
  876. `
  877. classesCHeader = gobindPreamble + `
  878. #include <jni.h>
  879. #include "seq.h"
  880. #include "classes.h"
  881. `
  882. classesHHeader = gobindPreamble + `
  883. #include <jni.h>
  884. #include "seq.h"
  885. extern void init_proxies();
  886. `
  887. javaImplHeader = gobindPreamble
  888. classesGoHeader = gobindPreamble + `
  889. package main
  890. /*
  891. #include <stdlib.h> // for free()
  892. #include <jni.h>
  893. #include "seq.h"
  894. #include "classes.h"
  895. */
  896. import "C"
  897. import (
  898. "Java"
  899. _seq "golang.org/x/mobile/bind/seq"
  900. )
  901. `
  902. )