2
0
mirror of synced 2025-02-23 06:48:15 +00:00

mobile/bind: allow bound packages to refer to imported bound packages

Multiple packages are already supported, but only as if each packages
were bound in isolation. This CL lets a bound package refer to other
bound packages in its exported functions, types and fields.

In Java, the JNI class jclass and constructor jmethodID are exported
so other packages can construct proxies of other packages' interfaces.

In ObjC, the class @interface declarations are moved from the package
.m file to its .h file to allow other packages to constructs its
interface proxies.

Add a supporting test package, secondpkg, and add Java and ObjC tests
for the new cross package functionality. Also add simplepkg for
testing corner cases where the generated Go file must not include its
bound package.

While we're here, stop generating Go proxy types for struct types;
only Go interfaces can be implemented in the foreign language.

Change-Id: Icbfa739c893703867d38a9100ed0928fbd7a660d
Reviewed-on: https://go-review.googlesource.com/20575
Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Elias Naur 2016-03-11 11:52:33 +01:00
parent 31eac4e11d
commit 7df33f4a5c
51 changed files with 601 additions and 333 deletions

View File

@ -20,7 +20,16 @@ import (
"io"
)
type fileType int
type (
GeneratorConfig struct {
Writer io.Writer
Fset *token.FileSet
Pkg *types.Package
AllPkg []*types.Package
}
fileType int
)
const (
Java fileType = iota
@ -33,17 +42,15 @@ const (
)
// GenJava generates a Java API from a Go package.
func GenJava(w io.Writer, fset *token.FileSet, pkg *types.Package, javaPkg string, ft fileType) error {
if javaPkg == "" {
javaPkg = javaPkgName(pkg.Name())
}
func GenJava(conf *GeneratorConfig, javaPkg string, ft fileType) error {
buf := new(bytes.Buffer)
g := &javaGen{
javaPkg: javaPkg,
generator: &generator{
printer: &printer{buf: buf, indentEach: []byte(" ")},
fset: fset,
pkg: pkg,
fset: conf.Fset,
allPkg: conf.AllPkg,
pkg: conf.Pkg,
},
}
g.init()
@ -61,18 +68,19 @@ func GenJava(w io.Writer, fset *token.FileSet, pkg *types.Package, javaPkg strin
if err != nil {
return err
}
_, err = io.Copy(w, buf)
_, err = io.Copy(conf.Writer, buf)
return err
}
// GenGo generates a Go stub to support foreign language APIs.
func GenGo(w io.Writer, fset *token.FileSet, pkg *types.Package) error {
func GenGo(conf *GeneratorConfig) error {
buf := new(bytes.Buffer)
g := &goGen{
&generator{
generator: &generator{
printer: &printer{buf: buf, indentEach: []byte("\t")},
fset: fset,
pkg: pkg,
fset: conf.Fset,
allPkg: conf.AllPkg,
pkg: conf.Pkg,
},
}
g.init()
@ -82,25 +90,22 @@ func GenGo(w io.Writer, fset *token.FileSet, pkg *types.Package) error {
src := buf.Bytes()
srcf, err := format.Source(src)
if err != nil {
w.Write(src) // for debugging
conf.Writer.Write(src) // for debugging
return err
}
_, err = w.Write(srcf)
_, err = conf.Writer.Write(srcf)
return err
}
// GenObjc generates the Objective-C API from a Go package.
func GenObjc(w io.Writer, fset *token.FileSet, pkg *types.Package, prefix string, ft fileType) error {
if prefix == "" {
prefix = "Go"
}
func GenObjc(conf *GeneratorConfig, prefix string, ft fileType) error {
buf := new(bytes.Buffer)
g := &objcGen{
generator: &generator{
printer: &printer{buf: buf, indentEach: []byte("\t")},
fset: fset,
pkg: pkg,
fset: conf.Fset,
allPkg: conf.AllPkg,
pkg: conf.Pkg,
},
prefix: prefix,
}
@ -119,6 +124,6 @@ func GenObjc(w io.Writer, fset *token.FileSet, pkg *types.Package, prefix string
if err != nil {
return err
}
_, err = io.Copy(w, buf)
_, err = io.Copy(conf.Writer, buf)
return err
}

View File

@ -100,7 +100,7 @@ func TestGenObjc(t *testing.T) {
for typ, suffix := range suffixes {
var buf bytes.Buffer
if err := GenObjc(&buf, fset, pkg, "", typ); err != nil {
if err := GenObjc(&buf, fset, pkg, []*types.Package{pkg}, "", typ); err != nil {
t.Errorf("%s: %v", filename, err)
continue
}
@ -132,7 +132,7 @@ func TestGenJava(t *testing.T) {
pkg := typeCheck(t, filename)
for typ, suffix := range suffixes {
var buf bytes.Buffer
if err := GenJava(&buf, fset, pkg, "", typ); err != nil {
if err := GenJava(&buf, fset, pkg, []*types.Package{pkg}, "", typ); err != nil {
t.Errorf("%s: %v", filename, err)
continue
}
@ -158,7 +158,7 @@ func TestGenGo(t *testing.T) {
for _, filename := range tests {
var buf bytes.Buffer
pkg := typeCheck(t, filename)
if err := GenGo(&buf, fset, pkg); err != nil {
if err := GenGo(&buf, fset, pkg, []*types.Package{pkg}); err != nil {
t.Errorf("%s: %v", filename, err)
continue
}
@ -189,27 +189,27 @@ func TestCustomPrefix(t *testing.T) {
}{
{
"testdata/customprefix.java.golden",
func(w io.Writer) error { return GenJava(w, fset, pkg, "com.example", Java) },
func(w io.Writer) error { return GenJava(w, fset, pkg, []*types.Package{pkg}, "com.example", Java) },
},
{
"testdata/customprefix.java.h.golden",
func(w io.Writer) error { return GenJava(w, fset, pkg, "com.example", JavaH) },
func(w io.Writer) error { return GenJava(w, fset, pkg, []*types.Package{pkg}, "com.example", JavaH) },
},
{
"testdata/customprefix.java.c.golden",
func(w io.Writer) error { return GenJava(w, fset, pkg, "com.example", JavaC) },
func(w io.Writer) error { return GenJava(w, fset, pkg, []*types.Package{pkg}, "com.example", JavaC) },
},
{
"testdata/customprefix.objc.go.h.golden",
func(w io.Writer) error { return GenObjc(w, fset, pkg, "EX", ObjcGoH) },
func(w io.Writer) error { return GenObjc(w, fset, pkg, []*types.Package{pkg}, "EX", ObjcGoH) },
},
{
"testdata/customprefix.objc.h.golden",
func(w io.Writer) error { return GenObjc(w, fset, pkg, "EX", ObjcH) },
func(w io.Writer) error { return GenObjc(w, fset, pkg, []*types.Package{pkg}, "EX", ObjcH) },
},
{
"testdata/customprefix.objc.m.golden",
func(w io.Writer) error { return GenObjc(w, fset, pkg, "EX", ObjcM) },
func(w io.Writer) error { return GenObjc(w, fset, pkg, []*types.Package{pkg}, "EX", ObjcM) },
},
}

View File

@ -52,14 +52,13 @@ func (list ErrorList) Error() string {
type generator struct {
*printer
fset *token.FileSet
pkg *types.Package
err ErrorList
fset *token.FileSet
allPkg []*types.Package
pkg *types.Package
err ErrorList
// fields set by init.
pkgName string
// pkgPrefix is a prefix for disambiguating
// function names for binding multiple packages
pkgName string
pkgPrefix string
funcs []*types.Func
constants []*types.Const
@ -70,12 +69,19 @@ type generator struct {
otherNames []*types.TypeName
}
// pkgPrefix returns a prefix that disambiguates symbol names for binding
// multiple packages.
//
// TODO(elias.naur): Avoid (and test) name clashes from multiple packages
// with the same name. Perhaps use the index from the order the package is
// generated.
func pkgPrefix(pkg *types.Package) string {
return pkg.Name()
}
func (g *generator) init() {
g.pkgName = g.pkg.Name()
// TODO(elias.naur): Avoid (and test) name clashes from multiple packages
// with the same name. Perhaps use the index from the order the package is
// generated.
g.pkgPrefix = g.pkgName
g.pkgPrefix = pkgPrefix(g.pkg)
scope := g.pkg.Scope()
hasExported := false
@ -223,6 +229,15 @@ func (g *generator) genInterfaceMethodSignature(m *types.Func, iName string, hea
}
}
func (g *generator) validPkg(pkg *types.Package) bool {
for _, p := range g.allPkg {
if p.Path() == pkg.Path() {
return true
}
}
return false
}
var paramRE = regexp.MustCompile(`^p[0-9]*$`)
// paramName replaces incompatible name with a p0-pN name.

View File

@ -5,6 +5,7 @@
package bind
import (
"bytes"
"fmt"
"go/types"
"strings"
@ -12,6 +13,7 @@ import (
type goGen struct {
*generator
imports map[string]struct{}
}
const (
@ -30,14 +32,6 @@ package gomobile_bind
*/
import "C"
import (
_seq "golang.org/x/mobile/bind/seq"
%[2]q
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
`
)
@ -129,11 +123,6 @@ func (g *goGen) genWrite(toVar, fromVar string, t types.Type, mode varMode) {
// TODO(crawshaw): test **Generator
switch t := t.Elem().(type) {
case *types.Named:
obj := t.Obj()
if obj.Pkg() != g.pkg {
g.errorf("type %s not defined in %s", t, g.pkg)
return
}
g.genToRefNum(toVar, fromVar)
default:
g.errorf("unsupported type %s", t)
@ -193,7 +182,7 @@ func (g *goGen) genFuncSignature(o *types.Func, objName string) {
func (g *goGen) genFunc(o *types.Func) {
g.genFuncSignature(o, "")
g.Indent()
g.genFuncBody(o, g.pkg.Name())
g.genFuncBody(o, g.pkgName(g.pkg))
g.Outdent()
g.Printf("}\n\n")
}
@ -202,15 +191,13 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) {
fields := exportedFields(T)
methods := exportedMethodSet(types.NewPointer(obj.Type()))
g.Printf("type proxy%s _seq.Ref\n\n", obj.Name())
for _, f := range fields {
g.Printf("//export proxy%s_%s_%s_Set\n", g.pkgPrefix, obj.Name(), f.Name())
g.Printf("func proxy%s_%s_%s_Set(refnum C.int32_t, v C.%s) {\n", g.pkgPrefix, obj.Name(), f.Name(), g.cgoType(f.Type()))
g.Indent()
g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
g.genRead("_v", "v", f.Type(), modeRetained)
g.Printf("ref.Get().(*%s.%s).%s = _v\n", g.pkg.Name(), obj.Name(), f.Name())
g.Printf("ref.Get().(*%s.%s).%s = _v\n", g.pkgName(g.pkg), obj.Name(), f.Name())
g.Outdent()
g.Printf("}\n\n")
@ -218,7 +205,7 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) {
g.Printf("func proxy%s_%s_%s_Get(refnum C.int32_t) C.%s {\n", g.pkgPrefix, obj.Name(), f.Name(), g.cgoType(f.Type()))
g.Indent()
g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
g.Printf("v := ref.Get().(*%s.%s).%s\n", g.pkg.Name(), obj.Name(), f.Name())
g.Printf("v := ref.Get().(*%s.%s).%s\n", g.pkgName(g.pkg), obj.Name(), f.Name())
g.genWrite("_v", "v", f.Type(), modeRetained)
g.Printf("return _v\n")
g.Outdent()
@ -229,7 +216,7 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) {
g.genFuncSignature(m, obj.Name())
g.Indent()
g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
g.Printf("v := ref.Get().(*%s.%s)\n", g.pkg.Name(), obj.Name())
g.Printf("v := ref.Get().(*%s.%s)\n", g.pkgName(g.pkg), obj.Name())
g.genFuncBody(m, "v")
g.Outdent()
g.Printf("}\n\n")
@ -239,7 +226,7 @@ func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) {
func (g *goGen) genVar(o *types.Var) {
// TODO(hyangah): non-struct pointer types (*int), struct type.
v := fmt.Sprintf("%s.%s", g.pkg.Name(), o.Name())
v := fmt.Sprintf("%s.%s", g.pkgName(g.pkg), o.Name())
// var I int
//
@ -273,7 +260,7 @@ func (g *goGen) genInterface(obj *types.TypeName) {
g.genFuncSignature(m, obj.Name())
g.Indent()
g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
g.Printf("v := ref.Get().(%s.%s)\n", g.pkg.Name(), obj.Name())
g.Printf("v := ref.Get().(%s.%s)\n", g.pkgName(g.pkg), obj.Name())
g.genFuncBody(m, "v")
g.Outdent()
g.Printf("}\n\n")
@ -383,13 +370,14 @@ func (g *goGen) genRead(toVar, fromVar string, typ types.Type, mode varMode) {
switch u := t.Elem().(type) {
case *types.Named:
o := u.Obj()
if o.Pkg() != g.pkg {
g.errorf("type %s not defined in %s", u, g.pkg)
oPkg := o.Pkg()
if !g.validPkg(oPkg) {
g.errorf("type %s is defined in %s, which is not bound", u, oPkg)
return
}
g.Printf("// Must be a Go object\n")
g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", toVar, fromVar)
g.Printf("%s := %s_ref.Get().(*%s.%s)\n", toVar, toVar, g.pkg.Name(), o.Name())
g.Printf("%s := %s_ref.Get().(*%s.%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
default:
g.errorf("unsupported pointer type %s", t)
}
@ -401,18 +389,19 @@ func (g *goGen) genRead(toVar, fromVar string, typ types.Type, mode varMode) {
hasProxy = makeIfaceSummary(iface).implementable
}
o := t.Obj()
if o.Pkg() != g.pkg {
g.errorf("type %s not defined in %s", t, g.pkg)
oPkg := o.Pkg()
if !g.validPkg(oPkg) {
g.errorf("type %s is defined in %s, which is not bound", t, oPkg)
return
}
g.Printf("var %s %s\n", toVar, g.typeString(t))
g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", toVar, fromVar)
g.Printf("if %s_ref != nil {\n", toVar)
g.Printf(" if %s_ref.Num < 0 { // go object \n", toVar)
g.Printf(" %s = %s_ref.Get().(%s.%s)\n", toVar, toVar, g.pkg.Name(), o.Name())
g.Printf(" %s = %s_ref.Get().(%s.%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
if hasProxy {
g.Printf(" } else { // foreign object \n")
g.Printf(" %s = (*proxy%s_%s)(%s_ref)\n", toVar, g.pkgPrefix, o.Name(), toVar)
g.Printf(" %s = (*proxy%s_%s)(%s_ref)\n", toVar, pkgPrefix(oPkg), o.Name(), toVar)
}
g.Printf(" }\n")
g.Printf("}\n")
@ -433,13 +422,15 @@ func (g *goGen) typeString(typ types.Type) string {
if obj.Pkg() == nil { // e.g. error type is *types.Named.
return types.TypeString(typ, types.RelativeTo(pkg))
}
if obj.Pkg() != g.pkg {
g.errorf("type %s not defined in %s", t, g.pkg)
oPkg := obj.Pkg()
if !g.validPkg(oPkg) {
g.errorf("type %s is defined in %s, which is not bound", t, oPkg)
return "TODO"
}
switch t.Underlying().(type) {
case *types.Interface, *types.Struct:
return fmt.Sprintf("%s.%s", pkg.Name(), types.TypeString(typ, types.RelativeTo(pkg)))
return fmt.Sprintf("%s.%s", g.pkgName(oPkg), types.TypeString(typ, types.RelativeTo(oPkg)))
default:
g.errorf("unsupported named type %s / %T", t, t)
}
@ -456,8 +447,30 @@ func (g *goGen) typeString(typ types.Type) string {
return ""
}
func (g *goGen) gen() error {
// genPreamble generates the preamble. It is generated after everything
// else, where we know which bound packages to import.
func (g *goGen) genPreamble() {
g.Printf(goPreamble, g.pkg.Name(), g.pkg.Path())
g.Printf("import (\n")
g.Indent()
g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n")
for path := range g.imports {
g.Printf("%q\n", path)
}
g.Outdent()
g.Printf(")\n\n")
}
func (g *goGen) gen() error {
g.imports = make(map[string]struct{})
// Switch to a temporary buffer so the preamble can be
// written last.
oldBuf := g.printer.buf
newBuf := new(bytes.Buffer)
g.printer.buf = newBuf
g.Printf("// suppress the error if seq ends up unused\n")
g.Printf("var _ = _seq.FromRefNum\n")
for _, s := range g.structs {
g.genStruct(s.obj, s.t)
@ -471,8 +484,20 @@ func (g *goGen) gen() error {
for _, f := range g.funcs {
g.genFunc(f)
}
// Switch to the original buffer, write the preamble
// and append the rest of the file.
g.printer.buf = oldBuf
g.genPreamble()
g.printer.buf.Write(newBuf.Bytes())
if len(g.err) > 0 {
return g.err
}
return nil
}
// pkgName retuns the package name and adds the package to the list of
// imports.
func (g *goGen) pkgName(pkg *types.Package) string {
g.imports[pkg.Path()] = struct{}{}
return pkg.Name()
}

View File

@ -16,6 +16,8 @@ import (
// TODO(crawshaw): consider introducing Java functions for casting to and from interfaces at runtime.
type javaGen struct {
// javaPkg is the custom name of the Java pkg that contains the generated classes. If empty,
// use a package name generated from the Go package name.
javaPkg string
*generator
@ -262,22 +264,24 @@ func (g *javaGen) javaType(T types.Type) string {
if _, ok := T.Elem().(*types.Named); ok {
return g.javaType(T.Elem())
}
panic(fmt.Sprintf("unsupported pointer to type: %s", T))
g.errorf("unsupported pointer to type: %s", T)
case *types.Named:
n := T.Obj()
if n.Pkg() != g.pkg {
nPkgName := "<nilpkg>"
if nPkg := n.Pkg(); nPkg != nil {
nPkgName = nPkg.Name()
}
panic(fmt.Sprintf("type %s is in package %s, must be defined in package %s", n.Name(), nPkgName, g.pkg.Name()))
nPkg := n.Pkg()
if !g.validPkg(nPkg) {
g.errorf("type %s is in %s, which is not bound", n.Name(), nPkg)
break
}
// TODO(crawshaw): more checking here
return n.Name()
if nPkg != g.pkg {
return fmt.Sprintf("%s.%s.%s", g.javaPkgName(nPkg), className(nPkg), n.Name())
} else {
return n.Name()
}
default:
g.errorf("unsupported javaType: %#+v, %s\n", T, T)
return "TODO"
}
return "TODO"
}
func (g *javaGen) genJNIFuncSignature(o *types.Func, sName string, proxy bool) {
@ -328,7 +332,7 @@ func (g *javaGen) genJNIFuncSignature(o *types.Func, sName string, proxy bool) {
}
func (g *javaGen) jniPkgName() string {
return strings.Replace(g.javaPkg, ".", "_", -1)
return strings.Replace(g.javaPkgName(g.pkg), ".", "_", -1)
}
func (g *javaGen) genFuncSignature(o *types.Func, static, header bool) {
@ -466,24 +470,14 @@ func (g *javaGen) genCToJava(toName, fromName string, t types.Type, mode varMode
// TODO(crawshaw): test **Generator
switch t := t.Elem().(type) {
case *types.Named:
o := t.Obj()
if o.Pkg() != g.pkg {
g.errorf("type %s not defined in %s", t, g.pkg)
return
}
g.Printf("jobject %s = go_seq_from_refnum(env, %s, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", toName, fromName, g.pkgPrefix, o.Name(), g.pkgPrefix, o.Name())
g.genFromRefnum(toName, fromName, t, t.Obj())
default:
g.errorf("unsupported type %s", t)
}
case *types.Named:
switch t.Underlying().(type) {
case *types.Interface, *types.Pointer:
o := t.Obj()
if o.Pkg() != g.pkg {
g.errorf("type %s not defined in %s", t, g.pkg)
return
}
g.Printf("jobject %s = go_seq_from_refnum(env, %s, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", toName, fromName, g.pkgPrefix, o.Name(), g.pkgPrefix, o.Name())
g.genFromRefnum(toName, fromName, t, t.Obj())
default:
g.errorf("unsupported, direct named type %s", t)
}
@ -492,9 +486,19 @@ func (g *javaGen) genCToJava(toName, fromName string, t types.Type, mode varMode
}
}
func (g *javaGen) genFromRefnum(toName, fromName string, t types.Type, o *types.TypeName) {
oPkg := o.Pkg()
if !g.validPkg(oPkg) {
g.errorf("type %s is defined in package %s, which is not bound", t, oPkg)
return
}
p := pkgPrefix(oPkg)
g.Printf("jobject %s = go_seq_from_refnum(env, %s, proxy_class_%s_%s, proxy_class_%s_%s_cons);\n", toName, fromName, p, o.Name(), p, o.Name())
}
func (g *javaGen) gobindOpts() string {
opts := []string{"-lang=java"}
if g.javaPkg != javaPkgName(g.pkg.Name()) {
if g.javaPkg != "" {
opts = append(opts, "-javapkg="+g.javaPkg)
}
return strings.Join(opts, " ")
@ -505,8 +509,11 @@ var javaNameReplacer = strings.NewReplacer(
".", "_",
)
func javaPkgName(pkgName string) string {
s := javaNameReplacer.Replace(pkgName)
func (g *javaGen) javaPkgName(pkg *types.Package) string {
if g.javaPkg != "" {
return g.javaPkg
}
s := javaNameReplacer.Replace(pkg.Name())
// Look for Java keywords that are not Go keywords, and avoid using
// them as a package name.
//
@ -528,7 +535,11 @@ func javaPkgName(pkgName string) string {
}
func (g *javaGen) className() string {
return strings.Title(javaNameReplacer.Replace(g.pkg.Name()))
return className(g.pkg)
}
func className(pkg *types.Package) string {
return strings.Title(javaNameReplacer.Replace(pkg.Name()))
}
func (g *javaGen) genConst(o *types.Const) {
@ -749,11 +760,18 @@ func (g *javaGen) genMethodInterfaceProxy(oName string, m *types.Func) {
func (g *javaGen) genH() error {
g.Printf(hPreamble, g.gobindOpts(), g.pkg.Path(), g.className())
for _, iface := range g.interfaces {
g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
g.Printf("\n")
for _, m := range iface.summary.callable {
g.genInterfaceMethodSignature(m, iface.obj.Name(), true)
g.Printf("\n")
}
}
for _, s := range g.structs {
g.Printf("extern jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
g.Printf("extern jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
}
g.Printf("#endif\n")
if len(g.err) > 0 {
return g.err
@ -805,7 +823,7 @@ func (g *javaGen) jniCallType(t types.Type) string {
}
func (g *javaGen) jniClassSigType(className string) string {
return strings.Replace(g.javaPkg, ".", "/", -1) + "/" + g.className() + "$" + className
return strings.Replace(g.javaPkgName(g.pkg), ".", "/", -1) + "/" + g.className() + "$" + className
}
func (g *javaGen) jniSigType(T types.Type) string {
@ -856,16 +874,24 @@ func (g *javaGen) jniSigType(T types.Type) string {
func (g *javaGen) genC() error {
g.Printf(cPreamble, g.gobindOpts(), g.pkg.Path(), g.pkg.Name())
g.Printf("#include %q\n", g.pkg.Name()+".h")
for _, pkg := range g.pkg.Imports() {
if g.validPkg(pkg) {
g.Printf("#include \"%s.h\"\n", pkg.Name())
}
}
g.Printf("\n")
for _, iface := range g.interfaces {
g.Printf("static jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
g.Printf("static jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, iface.obj.Name())
g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, iface.obj.Name())
for i := 0; i < iface.t.NumMethods(); i++ {
g.Printf("static jmethodID mid_%s_%s;\n", iface.obj.Name(), iface.t.Method(i).Name())
}
}
for _, s := range g.structs {
g.Printf("static jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
g.Printf("static jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
g.Printf("jclass proxy_class_%s_%s;\n", g.pkgPrefix, s.obj.Name())
g.Printf("jmethodID proxy_class_%s_%s_cons;\n", g.pkgPrefix, s.obj.Name())
}
g.Printf("\n")
g.Printf("JNIEXPORT void JNICALL\n")
@ -931,7 +957,7 @@ func (g *javaGen) genC() error {
}
func (g *javaGen) genJava() error {
g.Printf(javaPreamble, g.javaPkg, g.className(), g.gobindOpts(), g.pkg.Path())
g.Printf(javaPreamble, g.javaPkgName(g.pkg), g.className(), g.gobindOpts(), g.pkg.Path())
g.Printf("public abstract class %s {\n", g.className())
g.Indent()
@ -996,11 +1022,9 @@ import go.Seq;
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "%[3]s.h"
#include "_cgo_export.h"
`
hPreamble = `// JNI function headers for the Go <=> Java bridge.
// gobind %[1]s %[2]s
//

View File

@ -43,7 +43,15 @@ type structInfo struct {
func (g *objcGen) init() {
g.generator.init()
g.namePrefix = g.prefix + strings.Title(g.pkgName)
g.namePrefix = g.namePrefixOf(g.pkg)
}
func (g *objcGen) namePrefixOf(pkg *types.Package) string {
p := g.prefix
if p == "" {
p = "Go"
}
return p + strings.Title(pkg.Name())
}
func (g *objcGen) genGoH() error {
@ -73,10 +81,15 @@ func (g *objcGen) genGoH() error {
func (g *objcGen) genH() error {
g.Printf(objcPreamble, g.pkg.Path(), g.gobindOpts(), g.pkg.Path())
g.Printf("#ifndef __%s%s_H__\n", g.prefix, strings.Title(g.pkgName))
g.Printf("#define __%s%s_H__\n", g.prefix, strings.Title(g.pkgName))
g.Printf("#ifndef __%s_H__\n", g.namePrefix)
g.Printf("#define __%s_H__\n", g.namePrefix)
g.Printf("\n")
g.Printf("#include <Foundation/Foundation.h>\n")
for _, pkg := range g.pkg.Imports() {
if g.validPkg(pkg) {
g.Printf("#include %q\n", g.namePrefixOf(pkg)+".h")
}
}
g.Printf("\n")
// Forward declaration of @class and @protocol
@ -136,39 +149,6 @@ func (g *objcGen) genH() error {
g.Printf("\n")
}
// declare all named types first.
g.Printf("#endif\n")
if len(g.err) > 0 {
return g.err
}
return nil
}
func (g *objcGen) gobindOpts() string {
opts := []string{"-lang=objc"}
if g.prefix != "Go" {
opts = append(opts, "-prefix="+g.prefix)
}
return strings.Join(opts, " ")
}
func (g *objcGen) genM() error {
g.Printf(objcPreamble, g.pkg.Path(), g.gobindOpts(), g.pkg.Path())
g.Printf("#include %q\n", g.namePrefix+".h")
g.Printf("#include <Foundation/Foundation.h>\n")
g.Printf("#include \"seq.h\"\n")
g.Printf("#include \"_cgo_export.h\"\n")
g.Printf("\n")
g.Printf("static NSString* errDomain = @\"go.%s\";\n", g.pkg.Path())
g.Printf("\n")
g.Printf(`@protocol goSeqRefInterface
-(GoSeqRef*) _ref;
@end
`)
// forward declarations skipped from genH
for _, i := range g.interfaces {
if i.summary.implementable {
g.Printf("@class %s%s;\n\n", g.namePrefix, i.obj.Name())
@ -182,6 +162,37 @@ func (g *objcGen) genM() error {
}
}
g.Printf("#endif\n")
if len(g.err) > 0 {
return g.err
}
return nil
}
func (g *objcGen) gobindOpts() string {
opts := []string{"-lang=objc"}
if g.prefix != "" {
opts = append(opts, "-prefix="+g.prefix)
}
return strings.Join(opts, " ")
}
func (g *objcGen) genM() error {
g.Printf(objcPreamble, g.pkg.Path(), g.gobindOpts(), g.pkg.Path())
g.Printf("#include <Foundation/Foundation.h>\n")
g.Printf("#include \"seq.h\"\n")
g.Printf("#include \"_cgo_export.h\"\n")
g.Printf("#include %q\n", g.namePrefix+".h")
g.Printf("\n")
g.Printf("static NSString* errDomain = @\"go.%s\";\n", g.pkg.Path())
g.Printf("\n")
g.Printf(`@protocol goSeqRefInterface
-(GoSeqRef*) _ref;
@end
`)
// struct
for _, s := range g.structs {
g.genStructM(s.obj, s.t)
@ -889,10 +900,10 @@ func (g *objcGen) refTypeBase(typ types.Type) string {
}
case *types.Named:
n := typ.Obj()
if n.Pkg() == g.pkg {
if g.validPkg(n.Pkg()) {
switch typ.Underlying().(type) {
case *types.Interface, *types.Struct:
return g.namePrefix + n.Name()
return g.namePrefixOf(n.Pkg()) + n.Name()
}
}
}
@ -965,19 +976,19 @@ func (g *objcGen) objcType(typ types.Type) string {
return "TODO"
case *types.Named:
n := typ.Obj()
if n.Pkg() != g.pkg {
g.errorf("type %s is in package %s; only types defined in package %s is supported", n.Name(), n.Pkg().Name(), g.pkg.Name())
if !g.validPkg(n.Pkg()) {
g.errorf("type %s is in package %s, which is not bound", n.Name(), n.Pkg().Name())
return "TODO"
}
switch t := typ.Underlying().(type) {
case *types.Interface:
if makeIfaceSummary(t).implementable {
return "id<" + g.namePrefix + n.Name() + ">"
return "id<" + g.namePrefixOf(n.Pkg()) + n.Name() + ">"
} else {
return g.namePrefix + n.Name() + "*"
return g.namePrefixOf(n.Pkg()) + n.Name() + "*"
}
case *types.Struct:
return g.namePrefix + n.Name()
return g.namePrefixOf(n.Pkg()) + n.Name()
}
g.errorf("unsupported, named type %s", typ)
return "TODO"

View File

@ -11,6 +11,7 @@ import java.util.Arrays;
import java.util.Random;
import go.testpkg.Testpkg;
import go.secondpkg.Secondpkg;
public class SeqTest extends InstrumentationTestCase {
public SeqTest() {
@ -472,4 +473,23 @@ public class SeqTest extends InstrumentationTestCase {
}
});
}
public void testImportedPkg() {
assertEquals("imported string should match", Secondpkg.HelloString, Secondpkg.Hello());
Secondpkg.I i = Testpkg.NewImportedI();
Secondpkg.S s = Testpkg.NewImportedS();
i = Testpkg.getImportedVarI();
s = Testpkg.getImportedVarS();
assertEquals("numbers should match", 8, i.F(8));
assertEquals("numbers should match", 8, s.F(8));
Testpkg.setImportedVarI(i);
Testpkg.setImportedVarS(s);
Testpkg.ImportedFields fields = Testpkg.NewImportedFields();
i = fields.getI();
s = fields.getS();
fields.setI(i);
fields.setS(s);
Testpkg.WithImportedI(i);
Testpkg.WithImportedS(s);
}
}

View File

@ -20,7 +20,11 @@ import (
// This requires the gradle command in PATH and
// the Android SDK whose path is available through ANDROID_HOME environment variable.
func TestJavaSeqTest(t *testing.T) {
runTest(t, "golang.org/x/mobile/bind/testpkg", "SeqTest")
runTest(t, []string{
"golang.org/x/mobile/bind/testpkg",
"golang.org/x/mobile/bind/testpkg/secondpkg",
"golang.org/x/mobile/bind/testpkg/simplepkg",
}, "SeqTest")
}
// TestJavaSeqBench runs java test SeqBench.java, with the same
@ -34,10 +38,10 @@ func TestJavaSeqTest(t *testing.T) {
//
// while running the benchmark to see the results.
func TestJavaSeqBench(t *testing.T) {
runTest(t, "golang.org/x/mobile/bind/benchmark", "SeqBench")
runTest(t, []string{"golang.org/x/mobile/bind/benchmark"}, "SeqBench")
}
func runTest(t *testing.T, pkgName, javaCls string) {
func runTest(t *testing.T, pkgNames []string, javaCls string) {
if _, err := run("which gradle"); err != nil {
t.Skip("command gradle not found, skipping")
}
@ -80,7 +84,7 @@ func runTest(t *testing.T, pkgName, javaCls string) {
}
}
buf, err := run("gomobile bind -o pkg.aar " + pkgName)
buf, err := run("gomobile bind -o pkg.aar " + strings.Join(pkgNames, " "))
if err != nil {
t.Logf("%s", buf)
t.Fatalf("failed to run gomobile bind: %v", err)

View File

@ -348,4 +348,23 @@ static int numI = 0;
XCTAssertEqualObjects(got, want, @"want %@\nGoTestpkgReturnsError(TRUE) = (%@, %@)", want, value, got);
}
- (void)testImportedPkg {
XCTAssertEqualObjects(GoSecondpkgHelloString, GoSecondpkgHello(), @"imported string should match");
id<GoSecondpkgI> i = GoTestpkgNewImportedI();
GoSecondpkgS *s = GoTestpkgNewImportedS();
XCTAssertEqual(8, [i f:8], @"numbers should match");
XCTAssertEqual(8, [s f:8], @"numbers should match");
i = GoTestpkgWithImportedI(i);
s = GoTestpkgWithImportedS(s);
i = [GoTestpkg importedVarI];
s = [GoTestpkg importedVarS];
[GoTestpkg setImportedVarI:i];
[GoTestpkg setImportedVarS:s];
GoTestpkgImportedFields *fields = GoTestpkgNewImportedFields();
i = [fields i];
s = [fields s];
[fields setI:i];
[fields setS:s];
}
@end

View File

@ -38,16 +38,20 @@ var destination = flag.String("device", "platform=iOS Simulator,name=iPhone 6s P
// TestObjcSeqTest runs ObjC test SeqTest.m.
// This requires the xcode command lines tools.
func TestObjcSeqTest(t *testing.T) {
runTest(t, "golang.org/x/mobile/bind/testpkg", "xcodetest", "SeqTest.m", false)
runTest(t, []string{
"golang.org/x/mobile/bind/testpkg",
"golang.org/x/mobile/bind/testpkg/secondpkg",
"golang.org/x/mobile/bind/testpkg/simplepkg",
}, "xcodetest", "SeqTest.m", false)
}
// TestObjcSeqBench runs ObjC test SeqBench.m.
// This requires the xcode command lines tools.
func TestObjcSeqBench(t *testing.T) {
runTest(t, "golang.org/x/mobile/bind/benchmark", "xcodebench", "SeqBench.m", true)
runTest(t, []string{"golang.org/x/mobile/bind/benchmark"}, "xcodebench", "SeqBench.m", true)
}
func runTest(t *testing.T, pkgName, project, testfile string, dumpOutput bool) {
func runTest(t *testing.T, pkgNames []string, project, testfile string, dumpOutput bool) {
if _, err := run("which xcodebuild"); err != nil {
t.Skip("command xcodebuild not found, skipping")
}
@ -89,7 +93,7 @@ func runTest(t *testing.T, pkgName, project, testfile string, dumpOutput bool) {
}
defer os.Chdir(cwd)
buf, err := run("gomobile bind -target=ios " + pkgName)
buf, err := run("gomobile bind -target=ios " + strings.Join(pkgNames, " "))
if err != nil {
t.Logf("%s", buf)
t.Fatalf("failed to run gomobile bind: %v", err)

View File

@ -6,9 +6,8 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "basictypes.h"
#include "_cgo_export.h"
#include "basictypes.h"
JNIEXPORT void JNICALL

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoBasictypes.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoBasictypes.h"
static NSString* errDomain = @"go.basictypes";

View File

@ -6,9 +6,8 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "customprefix.h"
#include "_cgo_export.h"
#include "customprefix.h"
JNIEXPORT void JNICALL

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "EXCustomprefix.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "EXCustomprefix.h"
static NSString* errDomain = @"go.customprefix";

View File

@ -6,29 +6,28 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "interfaces.h"
#include "_cgo_export.h"
#include "interfaces.h"
static jclass proxy_class_interfaces_Error;
static jmethodID proxy_class_interfaces_Error_cons;
jclass proxy_class_interfaces_Error;
jmethodID proxy_class_interfaces_Error_cons;
static jmethodID mid_Error_Err;
static jclass proxy_class_interfaces_I;
static jmethodID proxy_class_interfaces_I_cons;
jclass proxy_class_interfaces_I;
jmethodID proxy_class_interfaces_I_cons;
static jmethodID mid_I_Rand;
static jclass proxy_class_interfaces_I1;
static jmethodID proxy_class_interfaces_I1_cons;
jclass proxy_class_interfaces_I1;
jmethodID proxy_class_interfaces_I1_cons;
static jmethodID mid_I1_H;
static jmethodID mid_I1_J;
static jclass proxy_class_interfaces_I2;
static jmethodID proxy_class_interfaces_I2_cons;
jclass proxy_class_interfaces_I2;
jmethodID proxy_class_interfaces_I2_cons;
static jmethodID mid_I2_G;
static jmethodID mid_I2_f;
static jclass proxy_class_interfaces_I3;
static jmethodID proxy_class_interfaces_I3_cons;
jclass proxy_class_interfaces_I3;
jmethodID proxy_class_interfaces_I3_cons;
static jmethodID mid_I3_F;
static jclass proxy_class_interfaces_WithParam;
static jmethodID proxy_class_interfaces_WithParam_cons;
jclass proxy_class_interfaces_WithParam;
jmethodID proxy_class_interfaces_WithParam_cons;
static jmethodID mid_WithParam_HasParam;
JNIEXPORT void JNICALL

View File

@ -8,16 +8,34 @@
#include <jni.h>
extern jclass proxy_class_interfaces_Error;
extern jmethodID proxy_class_interfaces_Error_cons;
nstring cproxyinterfaces_Error_Err(int32_t refnum);
extern jclass proxy_class_interfaces_I;
extern jmethodID proxy_class_interfaces_I_cons;
int32_t cproxyinterfaces_I_Rand(int32_t refnum);
extern jclass proxy_class_interfaces_I1;
extern jmethodID proxy_class_interfaces_I1_cons;
void cproxyinterfaces_I1_J(int32_t refnum);
extern jclass proxy_class_interfaces_I2;
extern jmethodID proxy_class_interfaces_I2_cons;
void cproxyinterfaces_I2_G(int32_t refnum);
extern jclass proxy_class_interfaces_I3;
extern jmethodID proxy_class_interfaces_I3_cons;
int32_t cproxyinterfaces_I3_F(int32_t refnum);
extern jclass proxy_class_interfaces_WithParam;
extern jmethodID proxy_class_interfaces_WithParam_cons;
void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0);
#endif

View File

@ -57,4 +57,44 @@ FOUNDATION_EXPORT BOOL GoInterfacesCallErr(id<GoInterfacesError> e, NSError** er
FOUNDATION_EXPORT id<GoInterfacesI> GoInterfacesSeven();
@class GoInterfacesError;
@class GoInterfacesI;
@class GoInterfacesI3;
@class GoInterfacesWithParam;
@interface GoInterfacesError : NSObject <GoInterfacesError> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (BOOL)err:(NSError**)error;
@end
@interface GoInterfacesI : NSObject <GoInterfacesI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (int32_t)rand;
@end
@interface GoInterfacesI3 : NSObject <GoInterfacesI3> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (GoInterfacesI1*)f;
@end
@interface GoInterfacesWithParam : NSObject <GoInterfacesWithParam> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)hasParam:(BOOL)p0;
@end
#endif

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoInterfaces.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoInterfaces.h"
static NSString* errDomain = @"go.interfaces";
@ -14,46 +14,6 @@ static NSString* errDomain = @"go.interfaces";
-(GoSeqRef*) _ref;
@end
@class GoInterfacesError;
@class GoInterfacesI;
@class GoInterfacesI3;
@class GoInterfacesWithParam;
@interface GoInterfacesError : NSObject <GoInterfacesError> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (BOOL)err:(NSError**)error;
@end
@interface GoInterfacesI : NSObject <GoInterfacesI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (int32_t)rand;
@end
@interface GoInterfacesI3 : NSObject <GoInterfacesI3> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (GoInterfacesI1*)f;
@end
@interface GoInterfacesWithParam : NSObject <GoInterfacesWithParam> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)hasParam:(BOOL)p0;
@end
@implementation GoInterfacesError {
}

View File

@ -21,8 +21,6 @@ import (
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
type proxyTestStruct _seq.Ref
//export proxyissue10788_TestStruct_Value_Set
func proxyissue10788_TestStruct_Value_Set(refnum C.int32_t, v C.nstring) {
ref := _seq.FromRefNum(int32(refnum))

View File

@ -6,16 +6,15 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "issue10788.h"
#include "_cgo_export.h"
#include "issue10788.h"
static jclass proxy_class_issue10788_TestInterface;
static jmethodID proxy_class_issue10788_TestInterface_cons;
jclass proxy_class_issue10788_TestInterface;
jmethodID proxy_class_issue10788_TestInterface_cons;
static jmethodID mid_TestInterface_DoSomeWork;
static jmethodID mid_TestInterface_MultipleUnnamedParams;
static jclass proxy_class_issue10788_TestStruct;
static jmethodID proxy_class_issue10788_TestStruct_cons;
jclass proxy_class_issue10788_TestStruct;
jmethodID proxy_class_issue10788_TestStruct_cons;
JNIEXPORT void JNICALL
Java_go_issue10788_Issue10788_init(JNIEnv *env, jclass _unused) {

View File

@ -8,8 +8,13 @@
#include <jni.h>
extern jclass proxy_class_issue10788_TestInterface;
extern jmethodID proxy_class_issue10788_TestInterface_cons;
void cproxyissue10788_TestInterface_DoSomeWork(int32_t refnum, int32_t s);
void cproxyissue10788_TestInterface_MultipleUnnamedParams(int32_t refnum, nint p0, nstring p1, int64_t p2);
extern jclass proxy_class_issue10788_TestStruct;
extern jmethodID proxy_class_issue10788_TestStruct_cons;
#endif

View File

@ -26,4 +26,15 @@
- (void)multipleUnnamedParams:(int)p0 p1:(NSString*)p1 p2:(int64_t)p2;
@end
@class GoIssue10788TestInterface;
@interface GoIssue10788TestInterface : NSObject <GoIssue10788TestInterface> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)doSomeWork:(GoIssue10788TestStruct*)s;
- (void)multipleUnnamedParams:(int)p0 p1:(NSString*)p1 p2:(int64_t)p2;
@end
#endif

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoIssue10788.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoIssue10788.h"
static NSString* errDomain = @"go.issue10788";
@ -14,17 +14,6 @@ static NSString* errDomain = @"go.issue10788";
-(GoSeqRef*) _ref;
@end
@class GoIssue10788TestInterface;
@interface GoIssue10788TestInterface : NSObject <GoIssue10788TestInterface> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)doSomeWork:(GoIssue10788TestStruct*)s;
- (void)multipleUnnamedParams:(int)p0 p1:(NSString*)p1 p2:(int64_t)p2;
@end
@implementation GoIssue10788TestStruct {
}

View File

@ -21,8 +21,6 @@ import (
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
type proxyT _seq.Ref
//export proxyissue12328_T_Err_Set
func proxyissue12328_T_Err_Set(refnum C.int32_t, v C.nstring) {
ref := _seq.FromRefNum(int32(refnum))

View File

@ -6,12 +6,11 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "issue12328.h"
#include "_cgo_export.h"
#include "issue12328.h"
static jclass proxy_class_issue12328_T;
static jmethodID proxy_class_issue12328_T_cons;
jclass proxy_class_issue12328_T;
jmethodID proxy_class_issue12328_T_cons;
JNIEXPORT void JNICALL
Java_go_issue12328_Issue12328_init(JNIEnv *env, jclass _unused) {

View File

@ -8,4 +8,6 @@
#include <jni.h>
extern jclass proxy_class_issue12328_T;
extern jmethodID proxy_class_issue12328_T_cons;
#endif

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoIssue12328.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoIssue12328.h"
static NSString* errDomain = @"go.issue12328";

View File

@ -6,12 +6,11 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "issue12403.h"
#include "_cgo_export.h"
#include "issue12403.h"
static jclass proxy_class_issue12403_Parsable;
static jmethodID proxy_class_issue12403_Parsable_cons;
jclass proxy_class_issue12403_Parsable;
jmethodID proxy_class_issue12403_Parsable_cons;
static jmethodID mid_Parsable_FromJSON;
static jmethodID mid_Parsable_ToJSON;

View File

@ -8,6 +8,9 @@
#include <jni.h>
extern jclass proxy_class_issue12403_Parsable;
extern jmethodID proxy_class_issue12403_Parsable_cons;
nstring cproxyissue12403_Parsable_FromJSON(int32_t refnum, nstring jstr);
typedef struct cproxyissue12403_Parsable_ToJSON_return {

View File

@ -16,4 +16,15 @@
- (BOOL)toJSON:(NSString**)ret0_ error:(NSError**)error;
@end
@class GoIssue12403Parsable;
@interface GoIssue12403Parsable : NSObject <GoIssue12403Parsable> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (NSString*)fromJSON:(NSString*)jstr;
- (BOOL)toJSON:(NSString**)ret0_ error:(NSError**)error;
@end
#endif

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoIssue12403.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoIssue12403.h"
static NSString* errDomain = @"go.issue12403";
@ -14,17 +14,6 @@ static NSString* errDomain = @"go.issue12403";
-(GoSeqRef*) _ref;
@end
@class GoIssue12403Parsable;
@interface GoIssue12403Parsable : NSObject <GoIssue12403Parsable> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (NSString*)fromJSON:(NSString*)jstr;
- (BOOL)toJSON:(NSString**)ret0_ error:(NSError**)error;
@end
@implementation GoIssue12403Parsable {
}

View File

@ -21,8 +21,6 @@ import (
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
type proxyS _seq.Ref
//export proxystructs_S_X_Set
func proxystructs_S_X_Set(refnum C.int32_t, v C.double) {
ref := _seq.FromRefNum(int32(refnum))
@ -81,8 +79,6 @@ func proxystructs_S_Sum(refnum C.int32_t) C.double {
return _res_0
}
type proxyS2 _seq.Ref
//export proxystructs_S2_M
func proxystructs_S2_M(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))

View File

@ -6,17 +6,16 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "structs.h"
#include "_cgo_export.h"
#include "structs.h"
static jclass proxy_class_structs_I;
static jmethodID proxy_class_structs_I_cons;
jclass proxy_class_structs_I;
jmethodID proxy_class_structs_I_cons;
static jmethodID mid_I_M;
static jclass proxy_class_structs_S;
static jmethodID proxy_class_structs_S_cons;
static jclass proxy_class_structs_S2;
static jmethodID proxy_class_structs_S2_cons;
jclass proxy_class_structs_S;
jmethodID proxy_class_structs_S_cons;
jclass proxy_class_structs_S2;
jmethodID proxy_class_structs_S2_cons;
JNIEXPORT void JNICALL
Java_go_structs_Structs_init(JNIEnv *env, jclass _unused) {

View File

@ -8,6 +8,13 @@
#include <jni.h>
extern jclass proxy_class_structs_I;
extern jmethodID proxy_class_structs_I_cons;
void cproxystructs_I_M(int32_t refnum);
extern jclass proxy_class_structs_S;
extern jmethodID proxy_class_structs_S_cons;
extern jclass proxy_class_structs_S2;
extern jmethodID proxy_class_structs_S2_cons;
#endif

View File

@ -42,4 +42,14 @@ FOUNDATION_EXPORT GoStructsS* GoStructsIdentity(GoStructsS* s);
FOUNDATION_EXPORT BOOL GoStructsIdentityWithError(GoStructsS* s, GoStructsS** ret0_, NSError** error);
@class GoStructsI;
@interface GoStructsI : NSObject <GoStructsI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)m;
@end
#endif

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoStructs.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoStructs.h"
static NSString* errDomain = @"go.structs";
@ -14,16 +14,6 @@ static NSString* errDomain = @"go.structs";
-(GoSeqRef*) _ref;
@end
@class GoStructsI;
@interface GoStructsI : NSObject <GoStructsI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
- (void)m;
@end
@implementation GoStructsS {
}

View File

@ -6,9 +6,8 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "try.h"
#include "_cgo_export.h"
#include "try.h"
JNIEXPORT void JNICALL

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoTry.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoTry.h"
static NSString* errDomain = @"go.try";

View File

@ -21,8 +21,6 @@ import (
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
type proxyS _seq.Ref
type proxyvars_I _seq.Ref
//export var_setvars_ABool

View File

@ -6,14 +6,13 @@
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "vars.h"
#include "_cgo_export.h"
#include "vars.h"
static jclass proxy_class_vars_I;
static jmethodID proxy_class_vars_I_cons;
static jclass proxy_class_vars_S;
static jmethodID proxy_class_vars_S_cons;
jclass proxy_class_vars_I;
jmethodID proxy_class_vars_I_cons;
jclass proxy_class_vars_S;
jmethodID proxy_class_vars_S_cons;
JNIEXPORT void JNICALL
Java_go_vars_Vars_init(JNIEnv *env, jclass _unused) {

View File

@ -8,4 +8,9 @@
#include <jni.h>
extern jclass proxy_class_vars_I;
extern jmethodID proxy_class_vars_I_cons;
extern jclass proxy_class_vars_S;
extern jmethodID proxy_class_vars_S_cons;
#endif

View File

@ -61,4 +61,13 @@
@end
@class GoVarsI;
@interface GoVarsI : NSObject <GoVarsI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
@end
#endif

View File

@ -3,10 +3,10 @@
//
// File is generated by gobind. Do not edit.
#include "GoVars.h"
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "GoVars.h"
static NSString* errDomain = @"go.vars";
@ -14,15 +14,6 @@ static NSString* errDomain = @"go.vars";
-(GoSeqRef*) _ref;
@end
@class GoVarsI;
@interface GoVarsI : NSObject <GoVarsI> {
}
@property(strong, readonly) id _ref;
- (id)initWithRef:(id)ref;
@end
@implementation GoVarsS {
}

View File

@ -0,0 +1,25 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package secondpkg is imported by bind tests that verify
// that a bound package can reference another bound package.
package secondpkg
type (
I interface {
F(i int) int
}
S struct{}
)
func (_ *S) F(i int) int {
return i
}
const HelloString = "secondpkg string"
func Hello() string {
return HelloString
}

View File

@ -0,0 +1,16 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package simplepkg is imported from testpkg and tests two
// corner cases.
// First: simplepkg itself contains no (exported) functions
// or methods and so its generated Go package must not import
// it.
//
// Second: even though testpkg imports simplepkg, testpkg's
// generated Go package ends up not referencing simplepkg and
// must not import it.
package simplepkg
type S struct{}

View File

@ -20,6 +20,9 @@ import (
"time"
"golang.org/x/mobile/asset"
"golang.org/x/mobile/bind/testpkg/secondpkg"
"golang.org/x/mobile/bind/testpkg/simplepkg"
)
const (
@ -411,3 +414,40 @@ type NullFieldStruct struct {
func NewNullFieldStruct() *NullFieldStruct {
return &NullFieldStruct{}
}
var (
ImportedVarI secondpkg.I = NewImportedI()
ImportedVarS *secondpkg.S = NewImportedS()
)
type ImportedFields struct {
I secondpkg.I
S *secondpkg.S
}
func NewImportedFields() *ImportedFields {
return &ImportedFields{
I: NewImportedI(),
S: NewImportedS(),
}
}
func NewImportedI() secondpkg.I {
return NewImportedS()
}
func NewImportedS() *secondpkg.S {
return new(secondpkg.S)
}
func WithImportedI(i secondpkg.I) secondpkg.I {
return i
}
func WithImportedS(s *secondpkg.S) *secondpkg.S {
return s
}
func NewSimpleS() *simplepkg.S {
return nil
}

View File

@ -16,36 +16,48 @@ import (
"golang.org/x/mobile/bind"
)
func genPkg(p *types.Package) {
func genPkg(p *types.Package, allPkg []*types.Package) {
fname := defaultFileName(*lang, p)
conf := &bind.GeneratorConfig{
Fset: fset,
Pkg: p,
AllPkg: allPkg,
}
switch *lang {
case "java":
w, closer := writer(fname)
processErr(bind.GenJava(w, fset, p, *javaPkg, bind.Java))
conf.Writer = w
processErr(bind.GenJava(conf, *javaPkg, bind.Java))
closer()
cname := "java_" + p.Name() + ".c"
w, closer = writer(cname)
processErr(bind.GenJava(w, fset, p, *javaPkg, bind.JavaC))
conf.Writer = w
processErr(bind.GenJava(conf, *javaPkg, bind.JavaC))
closer()
hname := p.Name() + ".h"
w, closer = writer(hname)
processErr(bind.GenJava(w, fset, p, *javaPkg, bind.JavaH))
conf.Writer = w
processErr(bind.GenJava(conf, *javaPkg, bind.JavaH))
closer()
case "go":
w, closer := writer(fname)
processErr(bind.GenGo(w, fset, p))
conf.Writer = w
processErr(bind.GenGo(conf))
closer()
case "objc":
gohname := p.Name() + ".h"
w, closer := writer(gohname)
processErr(bind.GenObjc(w, fset, p, *prefix, bind.ObjcGoH))
conf.Writer = w
processErr(bind.GenObjc(conf, *prefix, bind.ObjcGoH))
closer()
hname := fname[:len(fname)-2] + ".h"
w, closer = writer(hname)
processErr(bind.GenObjc(w, fset, p, *prefix, bind.ObjcH))
conf.Writer = w
processErr(bind.GenObjc(conf, *prefix, bind.ObjcH))
closer()
w, closer = writer(fname)
processErr(bind.GenObjc(w, fset, p, *prefix, bind.ObjcM))
conf.Writer = w
processErr(bind.GenObjc(conf, *prefix, bind.ObjcM))
closer()
default:
errorf("unknown target language: %q", *lang)

View File

@ -8,6 +8,7 @@ import (
"flag"
"fmt"
"go/importer"
"go/types"
"log"
"os"
"os/exec"
@ -46,13 +47,17 @@ func main() {
os.Exit(1)
}
var allPkg []*types.Package
for _, arg := range flag.Args() {
pkg, err := importer.Default().Import(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "could not import package %s: %v", arg, err)
os.Exit(1)
}
genPkg(pkg)
allPkg = append(allPkg, pkg)
}
for _, pkg := range allPkg {
genPkg(pkg, allPkg)
}
os.Exit(exitStatus)
}

View File

@ -160,7 +160,7 @@ func (b *binder) GenObjcSupport(outdir string) error {
return copyFile(filepath.Join(outdir, "seq.h"), filepath.Join(objcPkg.Dir, "seq.h"))
}
func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) {
func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir string) (string, error) {
const bindPrefixDefault = "Go"
if bindPrefix == "" {
bindPrefix = bindPrefixDefault
@ -176,6 +176,11 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) {
hfile := filepath.Join(outdir, fileBase+".h")
gohfile := filepath.Join(outdir, pkg.Name()+".h")
conf := &bind.GeneratorConfig{
Fset: b.fset,
Pkg: pkg,
AllPkg: allPkg,
}
generate := func(w io.Writer) error {
if buildX {
printcmd("gobind %s -outdir=%s %s", bindOption, outdir, pkg.Path())
@ -183,7 +188,8 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) {
if buildN {
return nil
}
return bind.GenObjc(w, b.fset, pkg, bindPrefix, bind.ObjcM)
conf.Writer = w
return bind.GenObjc(conf, bindPrefix, bind.ObjcM)
}
if err := writeFile(mfile, generate); err != nil {
return "", err
@ -192,7 +198,8 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) {
if buildN {
return nil
}
return bind.GenObjc(w, b.fset, pkg, bindPrefix, bind.ObjcH)
conf.Writer = w
return bind.GenObjc(conf, bindPrefix, bind.ObjcH)
}
if err := writeFile(hfile, generate); err != nil {
return "", err
@ -201,7 +208,8 @@ func (b *binder) GenObjc(pkg *types.Package, outdir string) (string, error) {
if buildN {
return nil
}
return bind.GenObjc(w, b.fset, pkg, bindPrefix, bind.ObjcGoH)
conf.Writer = w
return bind.GenObjc(conf, bindPrefix, bind.ObjcGoH)
}
if err := writeFile(gohfile, generate); err != nil {
return "", err
@ -224,7 +232,7 @@ func (b *binder) GenJavaSupport(outdir string) error {
return copyFile(filepath.Join(outdir, "seq.h"), filepath.Join(javaPkg.Dir, "seq.h"))
}
func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error {
func (b *binder) GenJava(pkg *types.Package, allPkg []*types.Package, outdir, javadir string) error {
className := strings.Title(pkg.Name())
javaFile := filepath.Join(javadir, className+".java")
cFile := filepath.Join(outdir, "java_"+pkg.Name()+".c")
@ -234,6 +242,11 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error {
bindOption += " -javapkg=" + bindJavaPkg
}
conf := &bind.GeneratorConfig{
Fset: b.fset,
Pkg: pkg,
AllPkg: allPkg,
}
generate := func(w io.Writer) error {
if buildX {
printcmd("gobind %s -outdir=%s %s", bindOption, javadir, pkg.Path())
@ -241,7 +254,8 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error {
if buildN {
return nil
}
return bind.GenJava(w, b.fset, pkg, bindJavaPkg, bind.Java)
conf.Writer = w
return bind.GenJava(conf, bindJavaPkg, bind.Java)
}
if err := writeFile(javaFile, generate); err != nil {
return err
@ -250,7 +264,8 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error {
if buildN {
return nil
}
return bind.GenJava(w, b.fset, pkg, bindJavaPkg, bind.JavaC)
conf.Writer = w
return bind.GenJava(conf, bindJavaPkg, bind.JavaC)
}
if err := writeFile(cFile, generate); err != nil {
return err
@ -259,12 +274,13 @@ func (b *binder) GenJava(pkg *types.Package, outdir, javadir string) error {
if buildN {
return nil
}
return bind.GenJava(w, b.fset, pkg, bindJavaPkg, bind.JavaH)
conf.Writer = w
return bind.GenJava(conf, bindJavaPkg, bind.JavaH)
}
return writeFile(hFile, generate)
}
func (b *binder) GenGo(pkg *types.Package, outdir string) error {
func (b *binder) GenGo(pkg *types.Package, allPkg []*types.Package, outdir string) error {
pkgName := "go_" + pkg.Name()
goFile := filepath.Join(outdir, pkgName+"main.go")
@ -275,7 +291,13 @@ func (b *binder) GenGo(pkg *types.Package, outdir string) error {
if buildN {
return nil
}
return bind.GenGo(w, b.fset, pkg)
conf := &bind.GeneratorConfig{
Writer: w,
Fset: b.fset,
Pkg: pkg,
AllPkg: allPkg,
}
return bind.GenGo(conf)
}
if err := writeFile(goFile, generate); err != nil {
return err

View File

@ -71,8 +71,8 @@ func goAndroidBind(pkgs []*build.Package, androidArchs []string) error {
}
srcDir := filepath.Join(tmpdir, "gomobile_bind")
for _, pkg := range typesPkgs {
if err := binder.GenGo(pkg, srcDir); err != nil {
for _, pkg := range binder.pkgs {
if err := binder.GenGo(pkg, binder.pkgs, srcDir); err != nil {
return err
}
}
@ -96,7 +96,7 @@ func goAndroidBind(pkgs []*build.Package, androidArchs []string) error {
if bindJavaPkg == "" {
pkgpath = "go/" + pkg.Name()
}
if err := binder.GenJava(pkg, srcDir, filepath.Join(androidDir, "src/main/java/"+pkgpath)); err != nil {
if err := binder.GenJava(pkg, binder.pkgs, srcDir, filepath.Join(androidDir, "src/main/java/"+pkgpath)); err != nil {
return err
}
}

View File

@ -36,8 +36,8 @@ func goIOSBind(pkgs []*build.Package) error {
}
srcDir := filepath.Join(tmpdir, "src", "gomobile_bind")
for _, pkg := range typesPkgs {
if err := binder.GenGo(pkg, srcDir); err != nil {
for _, pkg := range binder.pkgs {
if err := binder.GenGo(pkg, binder.pkgs, srcDir); err != nil {
return err
}
}
@ -51,8 +51,8 @@ func goIOSBind(pkgs []*build.Package) error {
}
fileBases := make([]string, len(typesPkgs))
for i, pkg := range typesPkgs {
if fileBases[i], err = binder.GenObjc(pkg, srcDir); err != nil {
for i, pkg := range binder.pkgs {
if fileBases[i], err = binder.GenObjc(pkg, binder.pkgs, srcDir); err != nil {
return err
}
}