1
0
Fork 0

Adding upstream version 0.0~git20250520.a1d9079+dfsg.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 19:46:29 +02:00
parent 590ac7ff5f
commit 20149b7f3a
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
456 changed files with 70406 additions and 0 deletions

59
bind/bind.go Normal file
View file

@ -0,0 +1,59 @@
// Copyright 2014 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 bind implements a code generator for gobind.
//
// See the documentation on the gobind command for usage details
// and the list of currently supported types.
// (http://godoc.org/golang.org/x/mobile/cmd/gobind)
package bind
// TODO(crawshaw): slice support
// TODO(crawshaw): channel support
import (
"bytes"
"go/format"
"go/token"
"go/types"
"io"
)
const gobindPreamble = "// Code generated by gobind. DO NOT EDIT.\n\n"
type (
GeneratorConfig struct {
Writer io.Writer
Fset *token.FileSet
Pkg *types.Package
AllPkg []*types.Package
}
fileType int
)
// GenGo generates a Go stub to support foreign language APIs.
func GenGo(conf *GeneratorConfig) error {
buf := new(bytes.Buffer)
g := &goGen{
Generator: &Generator{
Printer: &Printer{Buf: buf, IndentEach: []byte("\t")},
Fset: conf.Fset,
AllPkg: conf.AllPkg,
Pkg: conf.Pkg,
},
}
g.Init()
if err := g.gen(); err != nil {
return err
}
src := buf.Bytes()
srcf, err := format.Source(src)
if err != nil {
conf.Writer.Write(src) // for debugging
return err
}
_, err = conf.Writer.Write(srcf)
return err
}

703
bind/bind_test.go Normal file
View file

@ -0,0 +1,703 @@
// Copyright 2014 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 bind
import (
"bytes"
"flag"
"go/ast"
"go/build"
"go/format"
"go/importer"
"go/parser"
"go/token"
"go/types"
"io"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"testing"
"golang.org/x/mobile/internal/importers"
"golang.org/x/mobile/internal/importers/java"
"golang.org/x/mobile/internal/importers/objc"
)
func init() {
log.SetFlags(log.Lshortfile)
}
var updateFlag = flag.Bool("update", false, "Update the golden files.")
var tests = []string{
"", // The universe package with the error type.
"testdata/basictypes.go",
"testdata/structs.go",
"testdata/interfaces.go",
"testdata/issue10788.go",
"testdata/issue12328.go",
"testdata/issue12403.go",
"testdata/issue29559.go",
"testdata/keywords.go",
"testdata/try.go",
"testdata/vars.go",
"testdata/ignore.go",
"testdata/doc.go",
"testdata/underscores.go",
}
var javaTests = []string{
"testdata/java.go",
"testdata/classes.go",
}
var objcTests = []string{
"testdata/objc.go",
"testdata/objcw.go",
}
var fset = token.NewFileSet()
func fileRefs(t *testing.T, filename string, pkgPrefix string) *importers.References {
f, err := parser.ParseFile(fset, filename, nil, parser.AllErrors)
if err != nil {
t.Fatalf("%s: %v", filename, err)
}
refs, err := importers.AnalyzeFile(f, pkgPrefix)
if err != nil {
t.Fatalf("%s: %v", filename, err)
}
fakePath := path.Dir(filename)
for i := range refs.Embedders {
refs.Embedders[i].PkgPath = fakePath
}
return refs
}
func typeCheck(t *testing.T, filename string, gopath string) (*types.Package, *ast.File) {
f, err := parser.ParseFile(fset, filename, nil, parser.AllErrors|parser.ParseComments)
if err != nil {
t.Fatalf("%s: %v", filename, err)
}
pkgName := filepath.Base(filename)
pkgName = strings.TrimSuffix(pkgName, ".go")
// typecheck and collect typechecker errors
var conf types.Config
conf.Error = func(err error) {
t.Error(err)
}
if gopath != "" {
conf.Importer = importer.Default()
oldDefault := build.Default
defer func() { build.Default = oldDefault }()
build.Default.GOPATH = gopath
}
pkg, err := conf.Check(pkgName, fset, []*ast.File{f}, nil)
if err != nil {
t.Fatal(err)
}
return pkg, f
}
// diff runs the command "diff a b" and returns its output
func diff(a, b string) string {
var buf bytes.Buffer
var cmd *exec.Cmd
switch runtime.GOOS {
case "plan9":
cmd = exec.Command("/bin/diff", "-c", a, b)
default:
cmd = exec.Command("/usr/bin/diff", "-u", a, b)
}
cmd.Stdout = &buf
cmd.Stderr = &buf
cmd.Run()
return buf.String()
}
func writeTempFile(t *testing.T, name string, contents []byte) string {
f, err := os.CreateTemp("", name)
if err != nil {
t.Fatal(err)
}
if _, err := f.Write(contents); err != nil {
t.Fatal(err)
}
if err := f.Close(); err != nil {
t.Fatal(err)
}
return f.Name()
}
func TestGenObjc(t *testing.T) {
for _, filename := range tests {
var pkg *types.Package
var file *ast.File
if filename != "" {
pkg, file = typeCheck(t, filename, "")
}
var buf bytes.Buffer
g := &ObjcGen{
Generator: &Generator{
Printer: &Printer{Buf: &buf, IndentEach: []byte("\t")},
Fset: fset,
Files: []*ast.File{file},
Pkg: pkg,
},
}
if pkg != nil {
g.AllPkg = []*types.Package{pkg}
}
g.Init(nil)
testcases := []struct {
suffix string
gen func() error
}{
{
".objc.h.golden",
g.GenH,
},
{
".objc.m.golden",
g.GenM,
},
{
".objc.go.h.golden",
g.GenGoH,
},
}
for _, tc := range testcases {
buf.Reset()
if err := tc.gen(); err != nil {
t.Errorf("%s: %v", filename, err)
continue
}
out := writeTempFile(t, "generated"+tc.suffix, buf.Bytes())
defer os.Remove(out)
var golden string
if filename != "" {
golden = filename[:len(filename)-len(".go")]
} else {
golden = "testdata/universe"
}
golden += tc.suffix
if diffstr := diff(golden, out); diffstr != "" {
t.Errorf("%s: does not match Objective-C golden:\n%s", filename, diffstr)
if *updateFlag {
t.Logf("Updating %s...", golden)
err := exec.Command("/bin/cp", out, golden).Run()
if err != nil {
t.Errorf("Update failed: %s", err)
}
}
}
}
}
}
func genObjcPackages(t *testing.T, dir string, cg *ObjcWrapper) {
pkgBase := filepath.Join(dir, "src", "ObjC")
if err := os.MkdirAll(pkgBase, 0700); err != nil {
t.Fatal(err)
}
for i, jpkg := range cg.Packages() {
pkgDir := filepath.Join(pkgBase, jpkg)
if err := os.MkdirAll(pkgDir, 0700); err != nil {
t.Fatal(err)
}
pkgFile := filepath.Join(pkgDir, "package.go")
cg.Buf.Reset()
cg.GenPackage(i)
if err := os.WriteFile(pkgFile, cg.Buf.Bytes(), 0600); err != nil {
t.Fatal(err)
}
}
cg.Buf.Reset()
cg.GenInterfaces()
clsFile := filepath.Join(pkgBase, "interfaces.go")
if err := os.WriteFile(clsFile, cg.Buf.Bytes(), 0600); err != nil {
t.Fatal(err)
}
gocmd := filepath.Join(runtime.GOROOT(), "bin", "go")
cmd := exec.Command(
gocmd,
"install",
"-pkgdir="+filepath.Join(dir, "pkg", build.Default.GOOS+"_"+build.Default.GOARCH),
"ObjC/...",
)
cmd.Env = append(os.Environ(), "GOPATH="+dir, "GO111MODULE=off")
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("failed to go install the generated ObjC wrappers: %v: %s", err, string(out))
}
}
func genJavaPackages(t *testing.T, dir string, cg *ClassGen) {
buf := cg.Buf
cg.Buf = new(bytes.Buffer)
pkgBase := filepath.Join(dir, "src", "Java")
if err := os.MkdirAll(pkgBase, 0700); err != nil {
t.Fatal(err)
}
for i, jpkg := range cg.Packages() {
pkgDir := filepath.Join(pkgBase, jpkg)
if err := os.MkdirAll(pkgDir, 0700); err != nil {
t.Fatal(err)
}
pkgFile := filepath.Join(pkgDir, "package.go")
cg.Buf.Reset()
cg.GenPackage(i)
if err := os.WriteFile(pkgFile, cg.Buf.Bytes(), 0600); err != nil {
t.Fatal(err)
}
io.Copy(buf, cg.Buf)
}
cg.Buf.Reset()
cg.GenInterfaces()
clsFile := filepath.Join(pkgBase, "interfaces.go")
if err := os.WriteFile(clsFile, cg.Buf.Bytes(), 0600); err != nil {
t.Fatal(err)
}
io.Copy(buf, cg.Buf)
cg.Buf = buf
gocmd := filepath.Join(runtime.GOROOT(), "bin", "go")
cmd := exec.Command(
gocmd,
"install",
"-pkgdir="+filepath.Join(dir, "pkg", build.Default.GOOS+"_"+build.Default.GOARCH),
"Java/...",
)
cmd.Env = append(os.Environ(), "GOPATH="+dir, "GO111MODULE=off")
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("failed to go install the generated Java wrappers: %v: %s", err, string(out))
}
}
func TestGenJava(t *testing.T) {
allTests := tests
if java.IsAvailable() {
allTests = append(append([]string{}, allTests...), javaTests...)
}
for _, filename := range allTests {
var pkg *types.Package
var file *ast.File
var buf bytes.Buffer
var cg *ClassGen
var classes []*java.Class
if filename != "" {
refs := fileRefs(t, filename, "Java/")
imp := &java.Importer{}
var err error
classes, err = imp.Import(refs)
if err != nil {
t.Fatal(err)
}
tmpGopath := ""
if len(classes) > 0 {
tmpGopath, err = os.MkdirTemp(os.TempDir(), "gomobile-bind-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpGopath)
cg = &ClassGen{
Printer: &Printer{
IndentEach: []byte("\t"),
Buf: new(bytes.Buffer),
},
}
cg.Init(classes, refs.Embedders)
genJavaPackages(t, tmpGopath, cg)
cg.Buf = &buf
}
pkg, file = typeCheck(t, filename, tmpGopath)
}
g := &JavaGen{
Generator: &Generator{
Printer: &Printer{Buf: &buf, IndentEach: []byte(" ")},
Fset: fset,
Files: []*ast.File{file},
Pkg: pkg,
},
}
if pkg != nil {
g.AllPkg = []*types.Package{pkg}
}
g.Init(classes)
testCases := []struct {
suffix string
gen func() error
}{
{
".java.golden",
func() error {
for i := range g.ClassNames() {
if err := g.GenClass(i); err != nil {
return err
}
}
return g.GenJava()
},
},
{
".java.c.golden",
func() error {
if cg != nil {
cg.GenC()
}
return g.GenC()
},
},
{
".java.h.golden",
func() error {
if cg != nil {
cg.GenH()
}
return g.GenH()
},
},
}
for _, tc := range testCases {
buf.Reset()
if err := tc.gen(); err != nil {
t.Errorf("%s: %v", filename, err)
continue
}
out := writeTempFile(t, "generated"+tc.suffix, buf.Bytes())
defer os.Remove(out)
var golden string
if filename != "" {
golden = filename[:len(filename)-len(".go")]
} else {
golden = "testdata/universe"
}
golden += tc.suffix
if diffstr := diff(golden, out); diffstr != "" {
t.Errorf("%s: does not match Java golden:\n%s", filename, diffstr)
if *updateFlag {
t.Logf("Updating %s...", golden)
if err := exec.Command("/bin/cp", out, golden).Run(); err != nil {
t.Errorf("Update failed: %s", err)
}
}
}
}
}
}
func TestGenGo(t *testing.T) {
for _, filename := range tests {
var buf bytes.Buffer
var pkg *types.Package
if filename != "" {
pkg, _ = typeCheck(t, filename, "")
}
testGenGo(t, filename, &buf, pkg)
}
}
func TestGenGoJavaWrappers(t *testing.T) {
if !java.IsAvailable() {
t.Skipf("java is not available")
}
for _, filename := range javaTests {
var buf bytes.Buffer
refs := fileRefs(t, filename, "Java/")
imp := &java.Importer{}
classes, err := imp.Import(refs)
if err != nil {
t.Fatal(err)
}
tmpGopath, err := os.MkdirTemp(os.TempDir(), "gomobile-bind-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpGopath)
cg := &ClassGen{
Printer: &Printer{
IndentEach: []byte("\t"),
Buf: &buf,
},
}
cg.Init(classes, refs.Embedders)
genJavaPackages(t, tmpGopath, cg)
pkg, _ := typeCheck(t, filename, tmpGopath)
cg.GenGo()
testGenGo(t, filename, &buf, pkg)
}
}
func TestGenGoObjcWrappers(t *testing.T) {
if runtime.GOOS != "darwin" {
t.Skipf("can only generate objc wrappers on darwin")
}
for _, filename := range objcTests {
var buf bytes.Buffer
refs := fileRefs(t, filename, "ObjC/")
types, err := objc.Import(refs)
if err != nil {
t.Fatal(err)
}
tmpGopath, err := os.MkdirTemp(os.TempDir(), "gomobile-bind-test-")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpGopath)
cg := &ObjcWrapper{
Printer: &Printer{
IndentEach: []byte("\t"),
Buf: &buf,
},
}
var genNames []string
for _, emb := range refs.Embedders {
genNames = append(genNames, emb.Name)
}
cg.Init(types, genNames)
genObjcPackages(t, tmpGopath, cg)
pkg, _ := typeCheck(t, filename, tmpGopath)
cg.GenGo()
testGenGo(t, filename, &buf, pkg)
}
}
func testGenGo(t *testing.T, filename string, buf *bytes.Buffer, pkg *types.Package) {
conf := &GeneratorConfig{
Writer: buf,
Fset: fset,
Pkg: pkg,
}
if pkg != nil {
conf.AllPkg = []*types.Package{pkg}
}
if err := GenGo(conf); err != nil {
t.Errorf("%s: %v", filename, err)
return
}
// TODO(hyangah): let GenGo format the generated go files.
out := writeTempFile(t, "go", gofmt(t, buf.Bytes()))
defer os.Remove(out)
golden := filename
if golden == "" {
golden = "testdata/universe"
}
golden += ".golden"
goldenContents, err := os.ReadFile(golden)
if err != nil {
t.Fatalf("failed to read golden file: %v", err)
}
// format golden file using the current go version's formatting rule.
formattedGolden := writeTempFile(t, "go", gofmt(t, goldenContents))
defer os.Remove(formattedGolden)
if diffstr := diff(formattedGolden, out); diffstr != "" {
t.Errorf("%s: does not match Go golden:\n%s", filename, diffstr)
if *updateFlag {
t.Logf("Updating %s...", golden)
if err := exec.Command("/bin/cp", out, golden).Run(); err != nil {
t.Errorf("Update failed: %s", err)
}
}
}
}
// gofmt formats the collection of Go source files auto-generated by gobind.
func gofmt(t *testing.T, src []byte) []byte {
t.Helper()
buf := &bytes.Buffer{}
mark := []byte(gobindPreamble)
for i, c := range bytes.Split(src, mark) {
if i == 0 {
buf.Write(c)
continue
}
tmp := append(mark, c...)
out, err := format.Source(tmp)
if err != nil {
t.Fatalf("failed to format Go file: error=%v\n----\n%s\n----", err, tmp)
}
if _, err := buf.Write(out); err != nil {
t.Fatalf("failed to write formatted file to buffer: %v", err)
}
}
return buf.Bytes()
}
func TestCustomPrefix(t *testing.T) {
const datafile = "testdata/customprefix.go"
pkg, file := typeCheck(t, datafile, "")
type testCase struct {
golden string
gen func(w io.Writer) error
}
var buf bytes.Buffer
jg := &JavaGen{
JavaPkg: "com.example",
Generator: &Generator{
Printer: &Printer{Buf: &buf, IndentEach: []byte(" ")},
Fset: fset,
AllPkg: []*types.Package{pkg},
Files: []*ast.File{file},
Pkg: pkg,
},
}
jg.Init(nil)
testCases := []testCase{
{
"testdata/customprefix.java.golden",
func(w io.Writer) error {
buf.Reset()
for i := range jg.ClassNames() {
if err := jg.GenClass(i); err != nil {
return err
}
}
if err := jg.GenJava(); err != nil {
return err
}
_, err := io.Copy(w, &buf)
return err
},
},
{
"testdata/customprefix.java.h.golden",
func(w io.Writer) error {
buf.Reset()
if err := jg.GenH(); err != nil {
return err
}
_, err := io.Copy(w, &buf)
return err
},
},
{
"testdata/customprefix.java.c.golden",
func(w io.Writer) error {
buf.Reset()
if err := jg.GenC(); err != nil {
return err
}
_, err := io.Copy(w, &buf)
return err
},
},
}
for _, pref := range []string{"EX", ""} {
og := &ObjcGen{
Prefix: pref,
Generator: &Generator{
Printer: &Printer{Buf: &buf, IndentEach: []byte(" ")},
Fset: fset,
AllPkg: []*types.Package{pkg},
Pkg: pkg,
},
}
og.Init(nil)
testCases = append(testCases, []testCase{
{
"testdata/customprefix" + pref + ".objc.go.h.golden",
func(w io.Writer) error {
buf.Reset()
if err := og.GenGoH(); err != nil {
return err
}
_, err := io.Copy(w, &buf)
return err
},
},
{
"testdata/customprefix" + pref + ".objc.h.golden",
func(w io.Writer) error {
buf.Reset()
if err := og.GenH(); err != nil {
return err
}
_, err := io.Copy(w, &buf)
return err
},
},
{
"testdata/customprefix" + pref + ".objc.m.golden",
func(w io.Writer) error {
buf.Reset()
if err := og.GenM(); err != nil {
return err
}
_, err := io.Copy(w, &buf)
return err
},
},
}...)
}
for _, tc := range testCases {
var buf bytes.Buffer
if err := tc.gen(&buf); err != nil {
t.Errorf("generating %s: %v", tc.golden, err)
continue
}
out := writeTempFile(t, "generated", buf.Bytes())
defer os.Remove(out)
if diffstr := diff(tc.golden, out); diffstr != "" {
t.Errorf("%s: generated file does not match:\b%s", tc.golden, diffstr)
if *updateFlag {
t.Logf("Updating %s...", tc.golden)
err := exec.Command("/bin/cp", out, tc.golden).Run()
if err != nil {
t.Errorf("Update failed: %s", err)
}
}
}
}
}
func TestLowerFirst(t *testing.T) {
testCases := []struct {
in, want string
}{
{"", ""},
{"Hello", "hello"},
{"HelloGopher", "helloGopher"},
{"hello", "hello"},
{"ID", "id"},
{"IDOrName", "idOrName"},
{"ΓειαΣας", "γειαΣας"},
}
for _, tc := range testCases {
if got := lowerFirst(tc.in); got != tc.want {
t.Errorf("lowerFirst(%q) = %q; want %q", tc.in, got, tc.want)
}
}
}
// Test that typeName work for anonymous qualified fields.
func TestSelectorExprTypeName(t *testing.T) {
e, err := parser.ParseExprFrom(fset, "", "struct { bytes.Buffer }", 0)
if err != nil {
t.Fatal(err)
}
ft := e.(*ast.StructType).Fields.List[0].Type
if got, want := typeName(ft), "Buffer"; got != want {
t.Errorf("got: %q; want %q", got, want)
}
}

575
bind/gen.go Normal file
View file

@ -0,0 +1,575 @@
// Copyright 2015 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 bind
import (
"bytes"
"fmt"
"go/ast"
"go/token"
"go/types"
"io"
"regexp"
"strings"
"unicode"
"unicode/utf8"
)
type (
ErrorList []error
// varMode describes the lifetime of an argument or
// return value. Modes are used to guide the conversion
// of string and byte slice values across the language
// barrier. The same conversion mode must be used for
// both the conversion before a foreign call and the
// corresponding conversion after the call.
// See the mode* constants for a description of
// each mode.
varMode int
)
const (
// modeTransient are for function arguments that
// are not used after the function returns.
// Transient byte slices don't need copying
// when passed across the language barrier.
modeTransient varMode = iota
// modeRetained are for returned values and for function
// arguments that are used after the function returns.
// Retained byte slices need an intermediate copy.
modeRetained
)
func (list ErrorList) Error() string {
buf := new(bytes.Buffer)
for i, err := range list {
if i > 0 {
buf.WriteRune('\n')
}
io.WriteString(buf, err.Error())
}
return buf.String()
}
// interfaceInfo comes from Init and collects the auxiliary information
// needed to generate bindings for an exported Go interface in a bound
// package.
type interfaceInfo struct {
obj *types.TypeName
t *types.Interface
summary ifaceSummary
}
// structInfo comes from Init and collects the auxiliary information
// needed to generate bindings for an exported Go struct in a bound
// package.
type structInfo struct {
obj *types.TypeName
t *types.Struct
}
// Generator contains the common Go package information
// needed for the specific Go, Java, ObjC generators.
//
// After setting Printer, Fset, AllPkg, Pkg, the Init
// method is used to initialize the auxiliary information
// about the package to be generated, Pkg.
type Generator struct {
*Printer
Fset *token.FileSet
AllPkg []*types.Package
Files []*ast.File
Pkg *types.Package
err ErrorList
// fields set by init.
pkgName string
pkgPrefix string
funcs []*types.Func
constants []*types.Const
vars []*types.Var
interfaces []interfaceInfo
structs []structInfo
otherNames []*types.TypeName
// allIntf contains interfaces from all bound packages.
allIntf []interfaceInfo
docs pkgDocs
}
// A pkgDocs maps the name of each exported package-level declaration to its extracted documentation.
type pkgDocs map[string]*pkgDoc
type pkgDoc struct {
doc string
// Struct or interface fields and methods.
members map[string]string
}
// 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 {
// The error type has no package
if pkg == nil {
return ""
}
return pkg.Name()
}
func (g *Generator) Init() {
if g.Pkg != nil {
g.pkgName = g.Pkg.Name()
}
g.pkgPrefix = pkgPrefix(g.Pkg)
if g.Pkg != nil {
g.parseDocs()
scope := g.Pkg.Scope()
hasExported := false
for _, name := range scope.Names() {
obj := scope.Lookup(name)
if !obj.Exported() {
continue
}
hasExported = true
switch obj := obj.(type) {
case *types.Func:
if isCallable(obj) {
g.funcs = append(g.funcs, obj)
}
case *types.TypeName:
named, ok := obj.Type().(*types.Named)
if !ok {
continue
}
switch t := named.Underlying().(type) {
case *types.Struct:
g.structs = append(g.structs, structInfo{obj, t})
case *types.Interface:
g.interfaces = append(g.interfaces, interfaceInfo{obj, t, makeIfaceSummary(t)})
default:
g.otherNames = append(g.otherNames, obj)
}
case *types.Const:
g.constants = append(g.constants, obj)
case *types.Var:
g.vars = append(g.vars, obj)
default:
g.errorf("unsupported exported type for %s: %T", obj.Name(), obj)
}
}
if !hasExported {
g.errorf("no exported names in the package %q", g.Pkg.Path())
}
} else {
// Bind the single supported type from the universe scope, error.
errType := types.Universe.Lookup("error").(*types.TypeName)
t := errType.Type().Underlying().(*types.Interface)
g.interfaces = append(g.interfaces, interfaceInfo{errType, t, makeIfaceSummary(t)})
}
for _, p := range g.AllPkg {
scope := p.Scope()
for _, name := range scope.Names() {
obj := scope.Lookup(name)
if !obj.Exported() {
continue
}
if obj, ok := obj.(*types.TypeName); ok {
named, ok := obj.Type().(*types.Named)
if !ok {
continue
}
if t, ok := named.Underlying().(*types.Interface); ok {
g.allIntf = append(g.allIntf, interfaceInfo{obj, t, makeIfaceSummary(t)})
}
}
}
}
}
// parseDocs extracts documentation from a package in a form useful for lookups.
func (g *Generator) parseDocs() {
d := make(pkgDocs)
for _, f := range g.Files {
for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.GenDecl:
for _, spec := range decl.Specs {
switch spec := spec.(type) {
case *ast.TypeSpec:
d.addType(spec, decl.Doc)
case *ast.ValueSpec:
d.addValue(spec, decl.Doc)
}
}
case *ast.FuncDecl:
d.addFunc(decl)
}
}
}
g.docs = d
}
func (d pkgDocs) addValue(t *ast.ValueSpec, outerDoc *ast.CommentGroup) {
for _, n := range t.Names {
if !ast.IsExported(n.Name) {
continue
}
doc := t.Doc
if doc == nil {
doc = outerDoc
}
if doc != nil {
d[n.Name] = &pkgDoc{doc: doc.Text()}
}
}
}
func (d pkgDocs) addFunc(f *ast.FuncDecl) {
doc := f.Doc
if doc == nil {
return
}
fn := f.Name.Name
if !ast.IsExported(fn) {
return
}
if r := f.Recv; r != nil {
// f is a method.
n := typeName(r.List[0].Type)
pd, exists := d[n]
if !exists {
pd = &pkgDoc{members: make(map[string]string)}
d[n] = pd
}
pd.members[fn] = doc.Text()
} else {
// f is a function.
d[fn] = &pkgDoc{doc: doc.Text()}
}
}
func (d pkgDocs) addType(t *ast.TypeSpec, outerDoc *ast.CommentGroup) {
if !ast.IsExported(t.Name.Name) {
return
}
doc := t.Doc
if doc == nil {
doc = outerDoc
}
pd := d[t.Name.Name]
pd = &pkgDoc{members: make(map[string]string)}
d[t.Name.Name] = pd
if doc != nil {
pd.doc = doc.Text()
}
var fields *ast.FieldList
switch t := t.Type.(type) {
case *ast.StructType:
fields = t.Fields
case *ast.InterfaceType:
fields = t.Methods
}
if fields != nil {
for _, field := range fields.List {
if field.Doc != nil {
if field.Names == nil {
// Anonymous field. Extract name from its type.
if n := typeName(field.Type); ast.IsExported(n) {
pd.members[n] = field.Doc.Text()
}
}
for _, n := range field.Names {
if ast.IsExported(n.Name) {
pd.members[n.Name] = field.Doc.Text()
}
}
}
}
}
}
// typeName returns the type name T for expressions on the
// T, *T, **T (etc.) form.
func typeName(t ast.Expr) string {
switch t := t.(type) {
case *ast.StarExpr:
return typeName(t.X)
case *ast.Ident:
return t.Name
case *ast.SelectorExpr:
return t.Sel.Name
default:
return ""
}
}
func (d *pkgDoc) Doc() string {
if d == nil {
return ""
}
return d.doc
}
func (d *pkgDoc) Member(n string) string {
if d == nil {
return ""
}
return d.members[n]
}
// constructorType returns the type T for a function of the forms:
//
// func NewT...(...) *T
// func NewT...(...) (*T, error)
func (g *Generator) constructorType(f *types.Func) *types.TypeName {
sig := f.Type().(*types.Signature)
res := sig.Results()
if res.Len() != 1 && !(res.Len() == 2 && isErrorType(res.At(1).Type())) {
return nil
}
rt := res.At(0).Type()
pt, ok := rt.(*types.Pointer)
if !ok {
return nil
}
nt, ok := pt.Elem().(*types.Named)
if !ok {
return nil
}
obj := nt.Obj()
if !strings.HasPrefix(f.Name(), "New"+obj.Name()) {
return nil
}
return obj
}
func toCFlag(v bool) int {
if v {
return 1
}
return 0
}
func (g *Generator) errorf(format string, args ...interface{}) {
g.err = append(g.err, fmt.Errorf(format, args...))
}
// cgoType returns the name of a Cgo type suitable for converting a value of
// the given type.
func (g *Generator) cgoType(t types.Type) string {
switch t := t.(type) {
case *types.Basic:
switch t.Kind() {
case types.Bool, types.UntypedBool:
return "char"
case types.Int:
return "nint"
case types.Int8:
return "int8_t"
case types.Int16:
return "int16_t"
case types.Int32, types.UntypedRune: // types.Rune
return "int32_t"
case types.Int64, types.UntypedInt:
return "int64_t"
case types.Uint8: // types.Byte
return "uint8_t"
// TODO(crawshaw): case types.Uint, types.Uint16, types.Uint32, types.Uint64:
case types.Float32:
return "float"
case types.Float64, types.UntypedFloat:
return "double"
case types.String:
return "nstring"
default:
g.errorf("unsupported basic type: %s", t)
}
case *types.Slice:
switch e := t.Elem().(type) {
case *types.Basic:
switch e.Kind() {
case types.Uint8: // Byte.
return "nbyteslice"
default:
g.errorf("unsupported slice type: %s", t)
}
default:
g.errorf("unsupported slice type: %s", t)
}
case *types.Pointer:
if _, ok := t.Elem().(*types.Named); ok {
return g.cgoType(t.Elem())
}
g.errorf("unsupported pointer to type: %s", t)
case *types.Named:
return "int32_t"
default:
g.errorf("unsupported type: %s", t)
}
return "TODO"
}
func (g *Generator) genInterfaceMethodSignature(m *types.Func, iName string, header bool, g_paramName func(*types.Tuple, int) string) {
sig := m.Type().(*types.Signature)
params := sig.Params()
res := sig.Results()
if res.Len() == 0 {
g.Printf("void ")
} else {
if res.Len() == 1 {
g.Printf("%s ", g.cgoType(res.At(0).Type()))
} else {
if header {
g.Printf("typedef struct cproxy%s_%s_%s_return {\n", g.pkgPrefix, iName, m.Name())
g.Indent()
for i := 0; i < res.Len(); i++ {
t := res.At(i).Type()
g.Printf("%s r%d;\n", g.cgoType(t), i)
}
g.Outdent()
g.Printf("} cproxy%s_%s_%s_return;\n", g.pkgPrefix, iName, m.Name())
}
g.Printf("struct cproxy%s_%s_%s_return ", g.pkgPrefix, iName, m.Name())
}
}
g.Printf("cproxy%s_%s_%s(int32_t refnum", g.pkgPrefix, iName, m.Name())
for i := 0; i < params.Len(); i++ {
t := params.At(i).Type()
g.Printf(", %s %s", g.cgoType(t), g_paramName(params, i))
}
g.Printf(")")
if header {
g.Printf(";\n")
} else {
g.Printf(" {\n")
}
}
func (g *Generator) validPkg(pkg *types.Package) bool {
for _, p := range g.AllPkg {
if p == pkg {
return true
}
}
return false
}
// isSigSupported reports whether the generators can handle a given
// function signature.
func (g *Generator) isSigSupported(t types.Type) bool {
sig := t.(*types.Signature)
params := sig.Params()
for i := 0; i < params.Len(); i++ {
if !g.isSupported(params.At(i).Type()) {
return false
}
}
res := sig.Results()
for i := 0; i < res.Len(); i++ {
if !g.isSupported(res.At(i).Type()) {
return false
}
}
return true
}
// isSupported reports whether the generators can handle the type.
func (g *Generator) isSupported(t types.Type) bool {
if isErrorType(t) || isWrapperType(t) {
return true
}
switch t := t.(type) {
case *types.Basic:
switch t.Kind() {
case types.Bool, types.UntypedBool,
types.Int,
types.Int8, types.Uint8, // types.Byte
types.Int16,
types.Int32, types.UntypedRune, // types.Rune
types.Int64, types.UntypedInt,
types.Float32,
types.Float64, types.UntypedFloat,
types.String, types.UntypedString:
return true
}
return false
case *types.Slice:
switch e := t.Elem().(type) {
case *types.Basic:
return e.Kind() == types.Uint8
}
case *types.Pointer:
switch t := t.Elem().(type) {
case *types.Named:
return g.validPkg(t.Obj().Pkg())
}
case *types.Named:
switch t.Underlying().(type) {
case *types.Interface, *types.Pointer:
return g.validPkg(t.Obj().Pkg())
}
}
return false
}
var paramRE = regexp.MustCompile(`^p[0-9]*$`)
// basicParamName replaces incompatible name with a p0-pN name.
// Missing names, or existing names of the form p[0-9] are incompatible.
func basicParamName(params *types.Tuple, pos int) string {
name := params.At(pos).Name()
if name == "" || name[0] == '_' || paramRE.MatchString(name) {
name = fmt.Sprintf("p%d", pos)
}
return name
}
func lowerFirst(s string) string {
if s == "" {
return ""
}
var conv []rune
for len(s) > 0 {
r, n := utf8.DecodeRuneInString(s)
if !unicode.IsUpper(r) {
if l := len(conv); l > 1 {
conv[l-1] = unicode.ToUpper(conv[l-1])
}
return string(conv) + s
}
conv = append(conv, unicode.ToLower(r))
s = s[n:]
}
return string(conv)
}
// newNameSanitizer returns a functions that replaces all dashes and dots
// with underscores, as well as avoiding reserved words by suffixing such
// identifiers with underscores.
func newNameSanitizer(res []string) func(s string) string {
reserved := make(map[string]bool)
for _, word := range res {
reserved[word] = true
}
symbols := strings.NewReplacer(
"-", "_",
".", "_",
)
return func(s string) string {
if reserved[s] {
return s + "_"
}
return symbols.Replace(s)
}
}

948
bind/genclasses.go Normal file
View file

@ -0,0 +1,948 @@
// 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 bind
import (
"fmt"
"path"
"reflect"
"strings"
"unicode"
"unicode/utf8"
"golang.org/x/mobile/internal/importers"
"golang.org/x/mobile/internal/importers/java"
)
type (
// ClassGen generates Go and C stubs for Java classes so import statements
// on the form
//
//
// import "Java/classpath/to/Class"
//
// will work.
ClassGen struct {
*Printer
// JavaPkg is the Java package prefix for the generated classes. The prefix is prepended to the Go
// package name to create the full Java package name.
JavaPkg string
imported map[string]struct{}
// The list of imported Java classes
classes []*java.Class
// The list of Go package paths with Java interfaces inside
jpkgs []string
// For each Go package path, the list of Java classes.
typePkgs map[string][]*java.Class
// For each Go package path, the Java class with static functions
// or constants.
clsPkgs map[string]*java.Class
// goClsMap is the map of Java class names to Go type names, qualified with package name. Go types
// that implement Java classes need Super methods and Unwrap methods.
goClsMap map[string]string
// goClsImports is the list of imports of user packages that contains the Go types implementing Java
// classes.
goClsImports []string
}
)
func (g *ClassGen) isSupported(t *java.Type) bool {
switch t.Kind {
case java.Array:
// TODO: Support all array types
return t.Elem.Kind == java.Byte
default:
return true
}
}
func (g *ClassGen) isFuncSetSupported(fs *java.FuncSet) bool {
for _, f := range fs.Funcs {
if g.isFuncSupported(f) {
return true
}
}
return false
}
func (g *ClassGen) isFuncSupported(f *java.Func) bool {
for _, a := range f.Params {
if !g.isSupported(a) {
return false
}
}
if f.Ret != nil {
return g.isSupported(f.Ret)
}
return true
}
func (g *ClassGen) goType(t *java.Type, local bool) string {
if t == nil {
// interface{} is used for parameters types for overloaded methods
// where no common ancestor type exists.
return "interface{}"
}
switch t.Kind {
case java.Int:
return "int32"
case java.Boolean:
return "bool"
case java.Short:
return "int16"
case java.Char:
return "uint16"
case java.Byte:
return "byte"
case java.Long:
return "int64"
case java.Float:
return "float32"
case java.Double:
return "float64"
case java.String:
return "string"
case java.Array:
return "[]" + g.goType(t.Elem, local)
case java.Object:
name := goClsName(t.Class)
if !local {
name = "Java." + name
}
return name
default:
panic("invalid kind")
}
}
// Init initializes the class wrapper generator. Classes is the
// list of classes to wrap, goClasses is the list of Java classes
// implemented in Go.
func (g *ClassGen) Init(classes []*java.Class, goClasses []importers.Struct) {
g.goClsMap = make(map[string]string)
impMap := make(map[string]struct{})
for _, s := range goClasses {
n := s.Pkg + "." + s.Name
jn := n
if g.JavaPkg != "" {
jn = g.JavaPkg + "." + jn
}
g.goClsMap[jn] = n
if _, exists := impMap[s.PkgPath]; !exists {
impMap[s.PkgPath] = struct{}{}
g.goClsImports = append(g.goClsImports, s.PkgPath)
}
}
g.classes = classes
g.imported = make(map[string]struct{})
g.typePkgs = make(map[string][]*java.Class)
g.clsPkgs = make(map[string]*java.Class)
pkgSet := make(map[string]struct{})
for _, cls := range classes {
g.imported[cls.Name] = struct{}{}
clsPkg := strings.Replace(cls.Name, ".", "/", -1)
g.clsPkgs[clsPkg] = cls
typePkg := path.Dir(clsPkg)
g.typePkgs[typePkg] = append(g.typePkgs[typePkg], cls)
if _, exists := pkgSet[clsPkg]; !exists {
pkgSet[clsPkg] = struct{}{}
g.jpkgs = append(g.jpkgs, clsPkg)
}
if _, exists := pkgSet[typePkg]; !exists {
pkgSet[typePkg] = struct{}{}
g.jpkgs = append(g.jpkgs, typePkg)
}
}
}
// Packages return the list of Go packages to be generated.
func (g *ClassGen) Packages() []string {
return g.jpkgs
}
func (g *ClassGen) GenPackage(idx int) {
jpkg := g.jpkgs[idx]
g.Printf(gobindPreamble)
g.Printf("package %s\n\n", path.Base(jpkg))
g.Printf("import \"Java\"\n\n")
g.Printf("const _ = Java.Dummy\n\n")
for _, cls := range g.typePkgs[jpkg] {
g.Printf("type %s Java.%s\n", cls.PkgName, goClsName(cls.Name))
}
if cls, ok := g.clsPkgs[jpkg]; ok {
g.Printf("const (\n")
g.Indent()
// Constants
for _, v := range cls.Vars {
if g.isSupported(v.Type) && v.Constant() {
g.Printf("%s = %s\n", initialUpper(v.Name), v.Val)
}
}
g.Outdent()
g.Printf(")\n\n")
g.Printf("var (\n")
g.Indent()
// Functions
loop:
for _, fs := range cls.Funcs {
for _, f := range fs.Funcs {
if f.Public && g.isFuncSupported(f) {
g.Printf("%s func", fs.GoName)
g.genFuncDecl(false, fs)
g.Printf("\n")
continue loop
}
}
}
g.Printf("// Cast takes a proxy for a Java object and converts it to a %s proxy.\n", cls.Name)
g.Printf("// Cast panics if the argument is not a proxy or if the underlying object does\n")
g.Printf("// not extend or implement %s.\n", cls.Name)
g.Printf("Cast func(v interface{}) Java.%s\n", goClsName(cls.Name))
g.Outdent()
g.Printf(")\n\n")
}
}
func (g *ClassGen) GenGo() {
g.Printf(classesGoHeader)
for _, cls := range g.classes {
pkgName := strings.Replace(cls.Name, ".", "/", -1)
g.Printf("import %q\n", "Java/"+pkgName)
}
for _, imp := range g.goClsImports {
g.Printf("import %q\n", imp)
}
if len(g.classes) > 0 {
g.Printf("import \"unsafe\"\n\n")
g.Printf("import \"reflect\"\n\n")
g.Printf("import \"fmt\"\n\n")
}
g.Printf("type proxy interface { Bind_proxy_refnum__() int32 }\n\n")
g.Printf("// Suppress unused package error\n\n")
g.Printf("var _ = _seq.FromRefNum\n")
g.Printf("const _ = Java.Dummy\n\n")
g.Printf("//export initClasses\n")
g.Printf("func initClasses() {\n")
g.Indent()
g.Printf("C.init_proxies()\n")
for _, cls := range g.classes {
g.Printf("init_%s()\n", cls.JNIName)
}
g.Outdent()
g.Printf("}\n\n")
for _, cls := range g.classes {
g.genGo(cls)
}
}
func (g *ClassGen) GenH() {
g.Printf(classesHHeader)
for _, tn := range []string{"jint", "jboolean", "jshort", "jchar", "jbyte", "jlong", "jfloat", "jdouble", "nstring", "nbyteslice"} {
g.Printf("typedef struct ret_%s {\n", tn)
g.Printf(" %s res;\n", tn)
g.Printf(" jint exc;\n")
g.Printf("} ret_%s;\n", tn)
}
g.Printf("\n")
for _, cls := range g.classes {
for _, fs := range cls.AllMethods {
for _, f := range fs.Funcs {
if !g.isFuncSupported(f) {
continue
}
g.Printf("extern ")
g.genCMethodDecl("cproxy", cls.JNIName, f)
g.Printf(";\n")
if _, ok := g.goClsMap[cls.Name]; ok {
g.Printf("extern ")
g.genCMethodDecl("csuper", cls.JNIName, f)
g.Printf(";\n")
}
}
}
}
for _, cls := range g.classes {
g.genH(cls)
}
}
func (g *ClassGen) GenC() {
g.Printf(classesCHeader)
for _, cls := range g.classes {
g.Printf("static jclass class_%s;\n", cls.JNIName)
if _, ok := g.goClsMap[cls.Name]; ok {
g.Printf("static jclass sclass_%s;\n", cls.JNIName)
}
for _, fs := range cls.Funcs {
for _, f := range fs.Funcs {
if !f.Public || !g.isFuncSupported(f) {
continue
}
g.Printf("static jmethodID m_s_%s_%s;\n", cls.JNIName, f.JNIName)
}
}
for _, fs := range cls.AllMethods {
for _, f := range fs.Funcs {
if g.isFuncSupported(f) {
g.Printf("static jmethodID m_%s_%s;\n", cls.JNIName, f.JNIName)
if _, ok := g.goClsMap[cls.Name]; ok {
g.Printf("static jmethodID sm_%s_%s;\n", cls.JNIName, f.JNIName)
}
}
}
}
g.genC(cls)
}
g.Printf("\n")
g.Printf("void init_proxies() {\n")
g.Indent()
g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", len(g.classes))
g.Printf("jclass clazz;\n")
for _, cls := range g.classes {
g.Printf("clazz = go_seq_find_class(%q);\n", strings.Replace(cls.FindName, ".", "/", -1))
g.Printf("if (clazz != NULL) {\n")
g.Indent()
g.Printf("class_%s = (*env)->NewGlobalRef(env, clazz);\n", cls.JNIName)
if _, ok := g.goClsMap[cls.Name]; ok {
g.Printf("sclass_%s = (*env)->GetSuperclass(env, clazz);\n", cls.JNIName)
g.Printf("sclass_%s = (*env)->NewGlobalRef(env, sclass_%s);\n", cls.JNIName, cls.JNIName)
}
for _, fs := range cls.Funcs {
for _, f := range fs.Funcs {
if !f.Public || !g.isFuncSupported(f) {
continue
}
g.Printf("m_s_%s_%s = ", cls.JNIName, f.JNIName)
if f.Constructor {
g.Printf("go_seq_get_method_id(clazz, \"<init>\", %q);\n", f.Desc)
} else {
g.Printf("go_seq_get_static_method_id(clazz, %q, %q);\n", f.Name, f.Desc)
}
}
}
for _, fs := range cls.AllMethods {
for _, f := range fs.Funcs {
if g.isFuncSupported(f) {
g.Printf("m_%s_%s = go_seq_get_method_id(clazz, %q, %q);\n", cls.JNIName, f.JNIName, f.Name, f.Desc)
if _, ok := g.goClsMap[cls.Name]; ok {
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)
}
}
}
}
g.Outdent()
g.Printf("}\n")
}
g.Printf("go_seq_pop_local_frame(env);\n")
g.Outdent()
g.Printf("}\n\n")
for _, cls := range g.classes {
for _, fs := range cls.AllMethods {
for _, f := range fs.Funcs {
if !g.isFuncSupported(f) {
continue
}
g.genCMethodDecl("cproxy", cls.JNIName, f)
g.genCMethodBody(cls, f, false)
if _, ok := g.goClsMap[cls.Name]; ok {
g.genCMethodDecl("csuper", cls.JNIName, f)
g.genCMethodBody(cls, f, true)
}
}
}
}
}
func (g *ClassGen) GenInterfaces() {
g.Printf(classesPkgHeader)
for _, cls := range g.classes {
g.genInterface(cls)
}
}
func (g *ClassGen) genCMethodBody(cls *java.Class, f *java.Func, virtual bool) {
g.Printf(" {\n")
g.Indent()
// Add 1 for the 'this' argument
g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", len(f.Params)+1)
g.Printf("// Must be a Java object\n")
g.Printf("jobject _this = go_seq_from_refnum(env, this, NULL, NULL);\n")
for i, a := range f.Params {
g.genCToJava(fmt.Sprintf("a%d", i), a)
}
if f.Ret != nil {
g.Printf("%s res = ", f.Ret.JNIType())
}
g.Printf("(*env)->Call")
if virtual {
g.Printf("Nonvirtual")
}
if f.Ret != nil {
g.Printf("%s", f.Ret.JNICallType())
} else {
g.Printf("Void")
}
g.Printf("Method(env, _this, ")
if virtual {
g.Printf("sclass_%s, sm_%s_%s", cls.JNIName, cls.JNIName, f.JNIName)
} else {
g.Printf("m_%s_%s", cls.JNIName, f.JNIName)
}
for i := range f.Params {
g.Printf(", _a%d", i)
}
g.Printf(");\n")
g.Printf("jobject _exc = go_seq_get_exception(env);\n")
g.Printf("int32_t _exc_ref = go_seq_to_refnum(env, _exc);\n")
if f.Ret != nil {
g.genCRetClear("res", f.Ret, "_exc")
g.genJavaToC("res", f.Ret)
}
g.Printf("go_seq_pop_local_frame(env);\n")
if f.Ret != nil {
g.Printf("ret_%s __res = {_res, _exc_ref};\n", f.Ret.CType())
g.Printf("return __res;\n")
} else {
g.Printf("return _exc_ref;\n")
}
g.Outdent()
g.Printf("}\n\n")
}
func initialUpper(s string) string {
if s == "" {
return ""
}
r, n := utf8.DecodeRuneInString(s)
return string(unicode.ToUpper(r)) + s[n:]
}
func (g *ClassGen) genFuncDecl(local bool, fs *java.FuncSet) {
g.Printf("(")
for i, a := range fs.Params {
if i > 0 {
g.Printf(", ")
}
g.Printf("a%d ", i)
if i == len(fs.Params)-1 && fs.Variadic {
g.Printf("...")
}
g.Printf("%s", g.goType(a, local))
}
g.Printf(")")
if fs.Throws {
if fs.HasRet {
g.Printf(" (%s, error)", g.goType(fs.Ret, local))
} else {
g.Printf(" error")
}
} else if fs.HasRet {
g.Printf(" %s", g.goType(fs.Ret, local))
}
}
func (g *ClassGen) genC(cls *java.Class) {
for _, fs := range cls.Funcs {
for _, f := range fs.Funcs {
if !f.Public || !g.isFuncSupported(f) {
continue
}
g.genCFuncDecl(cls.JNIName, f)
g.Printf(" {\n")
g.Indent()
g.Printf("JNIEnv *env = go_seq_push_local_frame(%d);\n", len(f.Params))
for i, a := range f.Params {
g.genCToJava(fmt.Sprintf("a%d", i), a)
}
if f.Constructor {
g.Printf("jobject res = (*env)->NewObject(env")
} else if f.Ret != nil {
g.Printf("%s res = (*env)->CallStatic%sMethod(env", f.Ret.JNIType(), f.Ret.JNICallType())
} else {
g.Printf("(*env)->CallStaticVoidMethod(env")
}
g.Printf(", class_%s, m_s_%s_%s", cls.JNIName, cls.JNIName, f.JNIName)
for i := range f.Params {
g.Printf(", _a%d", i)
}
g.Printf(");\n")
g.Printf("jobject _exc = go_seq_get_exception(env);\n")
g.Printf("int32_t _exc_ref = go_seq_to_refnum(env, _exc);\n")
if f.Ret != nil {
g.genCRetClear("res", f.Ret, "_exc")
g.genJavaToC("res", f.Ret)
}
g.Printf("go_seq_pop_local_frame(env);\n")
if f.Ret != nil {
g.Printf("ret_%s __res = {_res, _exc_ref};\n", f.Ret.CType())
g.Printf("return __res;\n")
} else {
g.Printf("return _exc_ref;\n")
}
g.Outdent()
g.Printf("}\n\n")
}
}
}
func (g *ClassGen) genH(cls *java.Class) {
for _, fs := range cls.Funcs {
for _, f := range fs.Funcs {
if !f.Public || !g.isFuncSupported(f) {
continue
}
g.Printf("extern ")
g.genCFuncDecl(cls.JNIName, f)
g.Printf(";\n")
}
}
}
func (g *ClassGen) genCMethodDecl(prefix, jniName string, f *java.Func) {
if f.Ret != nil {
g.Printf("ret_%s", f.Ret.CType())
} else {
// Return only the exception, if any
g.Printf("jint")
}
g.Printf(" %s_%s_%s(jint this", prefix, jniName, f.JNIName)
for i, a := range f.Params {
g.Printf(", %s a%d", a.CType(), i)
}
g.Printf(")")
}
func (g *ClassGen) genCFuncDecl(jniName string, f *java.Func) {
if f.Ret != nil {
g.Printf("ret_%s", f.Ret.CType())
} else {
// Return only the exception, if any
g.Printf("jint")
}
g.Printf(" cproxy_s_%s_%s(", jniName, f.JNIName)
for i, a := range f.Params {
if i > 0 {
g.Printf(", ")
}
g.Printf("%s a%d", a.CType(), i)
}
g.Printf(")")
}
func (g *ClassGen) genGo(cls *java.Class) {
g.Printf("var class_%s C.jclass\n\n", cls.JNIName)
g.Printf("func init_%s() {\n", cls.JNIName)
g.Indent()
g.Printf("cls := C.CString(%q)\n", strings.Replace(cls.FindName, ".", "/", -1))
g.Printf("clazz := C.go_seq_find_class(cls)\n")
g.Printf("C.free(unsafe.Pointer(cls))\n")
// Before Go 1.11 clazz was a pointer value, an uintptr after.
g.Printf("if uintptr(clazz) == 0 {\n")
g.Printf(" return\n")
g.Printf("}\n")
g.Printf("class_%s = clazz\n", cls.JNIName)
for _, fs := range cls.Funcs {
var supported bool
for _, f := range fs.Funcs {
if f.Public && g.isFuncSupported(f) {
supported = true
break
}
}
if !supported {
continue
}
g.Printf("%s.%s = func", cls.PkgName, fs.GoName)
g.genFuncDecl(false, fs)
g.genFuncBody(cls, fs, "cproxy_s", true)
}
g.Printf("%s.Cast = func(v interface{}) Java.%s {\n", cls.PkgName, goClsName(cls.Name))
g.Indent()
g.Printf("t := reflect.TypeOf((*proxy_class_%s)(nil))\n", cls.JNIName)
g.Printf("cv := reflect.ValueOf(v).Convert(t).Interface().(*proxy_class_%s)\n", cls.JNIName)
g.Printf("ref := C.jint(_seq.ToRefNum(cv))\n")
g.Printf("if C.go_seq_isinstanceof(ref, class_%s) != 1 {\n", cls.JNIName)
g.Printf(" panic(fmt.Errorf(\"%%T is not an instance of %%s\", v, %q))\n", cls.Name)
g.Printf("}\n")
g.Printf("return cv\n")
g.Outdent()
g.Printf("}\n")
g.Outdent()
g.Printf("}\n\n")
g.Printf("type proxy_class_%s _seq.Ref\n\n", cls.JNIName)
g.Printf("func (p *proxy_class_%s) Bind_proxy_refnum__() int32 {\n", cls.JNIName)
g.Indent()
g.Printf("return (*_seq.Ref)(p).Bind_IncNum()\n")
g.Outdent()
g.Printf("}\n\n")
for _, fs := range cls.AllMethods {
if !g.isFuncSetSupported(fs) {
continue
}
g.Printf("func (p *proxy_class_%s) %s", cls.JNIName, fs.GoName)
g.genFuncDecl(false, fs)
g.genFuncBody(cls, fs, "cproxy", false)
}
if cls.Throwable {
g.Printf("func (p *proxy_class_%s) Error() string {\n", cls.JNIName)
g.Printf(" return p.ToString()\n")
g.Printf("}\n")
}
if goName, ok := g.goClsMap[cls.Name]; ok {
g.Printf("func (p *proxy_class_%s) Super() Java.%s {\n", cls.JNIName, goClsName(cls.Name))
g.Printf(" return &super_%s{p}\n", cls.JNIName)
g.Printf("}\n\n")
g.Printf("type super_%s struct {*proxy_class_%[1]s}\n\n", cls.JNIName)
g.Printf("func (p *proxy_class_%s) Unwrap() interface{} {\n", cls.JNIName)
g.Indent()
g.Printf("goRefnum := C.go_seq_unwrap(C.jint(p.Bind_proxy_refnum__()))\n")
g.Printf("return _seq.FromRefNum(int32(goRefnum)).Get().(*%s)\n", goName)
g.Outdent()
g.Printf("}\n\n")
for _, fs := range cls.AllMethods {
if !g.isFuncSetSupported(fs) {
continue
}
g.Printf("func (p *super_%s) %s", cls.JNIName, fs.GoName)
g.genFuncDecl(false, fs)
g.genFuncBody(cls, fs, "csuper", false)
}
}
}
// genFuncBody generated a Go function body for a FuncSet. It resolves overloading dynamically,
// by inspecting the number of arguments (if the FuncSet contains varying parameter counts),
// and their types.
func (g *ClassGen) genFuncBody(cls *java.Class, fs *java.FuncSet, prefix string, static bool) {
maxp := len(fs.Funcs[0].Params)
minp := maxp
// sort the function variants into argument sizes.
buckets := make(map[int][]*java.Func)
numF := 0
for _, f := range fs.Funcs {
if !g.isFuncSupported(f) {
continue
}
numF++
n := len(f.Params)
if n < minp {
minp = n
} else if n > maxp {
maxp = n
}
buckets[n] = append(buckets[n], f)
}
g.Printf(" {\n")
g.Indent()
if len(buckets) != 1 {
// Switch over the number of arguments.
g.Printf("switch %d + len(a%d) {\n", minp, minp)
}
for i := minp; i <= maxp; i++ {
funcs := buckets[i]
if len(funcs) == 0 {
continue
}
if len(buckets) != 1 {
g.Printf("case %d:\n", i)
g.Indent()
}
for _, f := range funcs {
if len(funcs) > 1 {
g.Printf("{\n")
g.Indent()
}
var argNames []string
var preds []string
for i, a := range f.Params {
var ct *java.Type
var argName string
if i >= minp {
argName = fmt.Sprintf("a%d[%d]", minp, i-minp)
ct = fs.Params[minp]
} else {
argName = fmt.Sprintf("a%d", i)
ct = fs.Params[i]
}
if !reflect.DeepEqual(ct, a) {
g.Printf("_a%d, ok%d := %s.(%s)\n", i, i, argName, g.goType(a, false))
argName = fmt.Sprintf("_a%d", i)
preds = append(preds, fmt.Sprintf("ok%d", i))
}
argNames = append(argNames, argName)
}
if len(preds) > 0 {
g.Printf("if %s {\n", strings.Join(preds, " && "))
g.Indent()
}
for i, a := range f.Params {
g.genWrite(fmt.Sprintf("__a%d", i), argNames[i], a, modeTransient)
}
g.Printf("res := C.%s_%s_%s(", prefix, cls.JNIName, f.JNIName)
if !static {
g.Printf("C.jint(p.Bind_proxy_refnum__())")
}
for i := range f.Params {
if !static || i > 0 {
g.Printf(", ")
}
g.Printf("__a%d", i)
}
g.Printf(")\n")
g.genFuncRet(fs, f, numF > 1)
if len(preds) > 0 {
g.Outdent()
g.Printf("}\n")
}
if len(funcs) > 1 {
g.Outdent()
g.Printf("}\n")
}
}
if len(buckets) != 1 {
g.Outdent()
}
}
if len(buckets) != 1 {
g.Printf("}\n")
}
if numF > 1 {
g.Printf("panic(\"no overloaded method found for %s.%s that matched the arguments\")\n", cls.Name, fs.Name)
}
g.Outdent()
g.Printf("}\n\n")
}
func (g *ClassGen) genFuncRet(fs *java.FuncSet, f *java.Func, mustReturn bool) {
if f.Ret != nil {
g.genRead("_res", "res.res", f.Ret, modeRetained)
g.genRefRead("_exc", "res.exc", "error", "proxy_error", true)
} else {
g.genRefRead("_exc", "res", "error", "proxy_error", true)
}
if !fs.Throws {
g.Printf("if (_exc != nil) { panic(_exc) }\n")
if fs.HasRet {
if f.Ret != nil {
g.Printf("return _res\n")
} else {
// The variant doesn't return a value, but the common
// signature does. Use nil as a placeholder return value.
g.Printf("return nil\n")
}
} else if mustReturn {
// If there are overloaded variants, return here to avoid the fallback
// panic generated in genFuncBody.
g.Printf("return\n")
}
} else {
if fs.HasRet {
if f.Ret != nil {
g.Printf("return _res, _exc\n")
} else {
// As above, use a nil placeholder return value.
g.Printf("return nil, _exc\n")
}
} else {
g.Printf("return _exc\n")
}
}
}
func (g *ClassGen) genRead(to, from string, t *java.Type, mode varMode) {
switch t.Kind {
case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double:
g.Printf("%s := %s(%s)\n", to, g.goType(t, false), from)
case java.Boolean:
g.Printf("%s := %s != C.JNI_FALSE\n", to, from)
case java.String:
g.Printf("%s := decodeString(%s)\n", to, from)
case java.Array:
if t.Elem.Kind != java.Byte {
panic("unsupported array type")
}
g.Printf("%s := toSlice(%s, %v)\n", to, from, mode == modeRetained)
case java.Object:
_, hasProxy := g.imported[t.Class]
g.genRefRead(to, from, g.goType(t, false), "proxy_class_"+flattenName(t.Class), hasProxy)
default:
panic("invalid kind")
}
}
func (g *ClassGen) genRefRead(to, from string, intfName, proxyName string, hasProxy bool) {
g.Printf("var %s %s\n", to, intfName)
g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", to, from)
g.Printf("if %s_ref != nil {\n", to)
g.Printf(" if %s < 0 { // go object\n", from)
g.Printf(" %s = %s_ref.Get().(%s)\n", to, to, intfName)
g.Printf(" } else { // foreign object\n")
if hasProxy {
g.Printf(" %s = (*%s)(%s_ref)\n", to, proxyName, to)
} else {
g.Printf(" %s = %s_ref\n", to, to)
}
g.Printf(" }\n")
g.Printf("}\n")
}
func (g *ClassGen) genWrite(dst, v string, t *java.Type, mode varMode) {
switch t.Kind {
case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double:
g.Printf("%s := C.%s(%s)\n", dst, t.CType(), v)
case java.Boolean:
g.Printf("%s := C.jboolean(C.JNI_FALSE)\n", dst)
g.Printf("if %s {\n", v)
g.Printf(" %s = C.jboolean(C.JNI_TRUE)\n", dst)
g.Printf("}\n")
case java.String:
g.Printf("%s := encodeString(%s)\n", dst, v)
case java.Array:
if t.Elem.Kind != java.Byte {
panic("unsupported array type")
}
g.Printf("%s := fromSlice(%s, %v)\n", dst, v, mode == modeRetained)
case java.Object:
g.Printf("var %s C.jint = _seq.NullRefNum\n", dst)
g.Printf("if %s != nil {\n", v)
g.Printf(" %s = C.jint(_seq.ToRefNum(%s))\n", dst, v)
g.Printf("}\n")
default:
panic("invalid kind")
}
}
// genCRetClear clears the result value from a JNI call if an exception was
// raised.
func (g *ClassGen) genCRetClear(v string, t *java.Type, exc string) {
g.Printf("if (%s != NULL) {\n", exc)
g.Indent()
switch t.Kind {
case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double, java.Boolean:
g.Printf("%s = 0;\n", v)
default:
// Assume a nullable type. It will break if we missed a type.
g.Printf("%s = NULL;\n", v)
}
g.Outdent()
g.Printf("}\n")
}
func (g *ClassGen) genJavaToC(v string, t *java.Type) {
switch t.Kind {
case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double, java.Boolean:
g.Printf("%s _%s = %s;\n", t.JNIType(), v, v)
case java.String:
g.Printf("nstring _%s = go_seq_from_java_string(env, %s);\n", v, v)
case java.Array:
if t.Elem.Kind != java.Byte {
panic("unsupported array type")
}
g.Printf("nbyteslice _%s = go_seq_from_java_bytearray(env, %s, 1);\n", v, v)
case java.Object:
g.Printf("jint _%s = go_seq_to_refnum(env, %s);\n", v, v)
default:
panic("invalid kind")
}
}
func (g *ClassGen) genCToJava(v string, t *java.Type) {
switch t.Kind {
case java.Int, java.Short, java.Char, java.Byte, java.Long, java.Float, java.Double, java.Boolean:
g.Printf("%s _%s = %s;\n", t.JNIType(), v, v)
case java.String:
g.Printf("jstring _%s = go_seq_to_java_string(env, %s);\n", v, v)
case java.Array:
if t.Elem.Kind != java.Byte {
panic("unsupported array type")
}
g.Printf("jbyteArray _%s = go_seq_to_java_bytearray(env, %s, 0);\n", v, v)
case java.Object:
g.Printf("jobject _%s = go_seq_from_refnum(env, %s, NULL, NULL);\n", v, v)
default:
panic("invalid kind")
}
}
func goClsName(n string) string {
return initialUpper(strings.Replace(n, ".", "_", -1))
}
func (g *ClassGen) genInterface(cls *java.Class) {
g.Printf("type %s interface {\n", goClsName(cls.Name))
g.Indent()
// Methods
for _, fs := range cls.AllMethods {
if !g.isFuncSetSupported(fs) {
continue
}
g.Printf("%s", fs.GoName)
g.genFuncDecl(true, fs)
g.Printf("\n")
}
if goName, ok := g.goClsMap[cls.Name]; ok {
g.Printf("Super() %s\n", goClsName(cls.Name))
g.Printf("// Unwrap returns the Go object this Java instance\n")
g.Printf("// is wrapping.\n")
g.Printf("// The return value is a %s, but the delclared type is\n", goName)
g.Printf("// interface{} to avoid import cycles.\n")
g.Printf("Unwrap() interface{}\n")
}
if cls.Throwable {
g.Printf("Error() string\n")
}
g.Outdent()
g.Printf("}\n\n")
}
// Flatten java class names. "java.package.Class$Inner" is converted to
// "java_package_Class_Inner"
func flattenName(n string) string {
return strings.Replace(strings.Replace(n, ".", "_", -1), "$", "_", -1)
}
const (
classesPkgHeader = gobindPreamble + `
package Java
// Used to silence this package not used errors
const Dummy = 0
`
classesCHeader = gobindPreamble + `
#include <jni.h>
#include "seq.h"
#include "classes.h"
`
classesHHeader = gobindPreamble + `
#include <jni.h>
#include "seq.h"
extern void init_proxies();
`
javaImplHeader = gobindPreamble
classesGoHeader = gobindPreamble + `
package main
/*
#include <stdlib.h> // for free()
#include <jni.h>
#include "seq.h"
#include "classes.h"
*/
import "C"
import (
"Java"
_seq "golang.org/x/mobile/bind/seq"
)
`
)

593
bind/gengo.go Normal file
View file

@ -0,0 +1,593 @@
// Copyright 2014 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 bind
import (
"bytes"
"fmt"
"go/types"
"strings"
)
type goGen struct {
*Generator
// imports is the list of imports, in the form
// "the/package/path"
//
// or
//
// name "the/package/path"
//
// in case of duplicates.
imports []string
// The set of taken import names.
importNames map[string]struct{}
// importMap is a map from packages to their names. The name of a package is the last
// segment of its path, with duplicates resolved by appending a underscore and a unique
// number.
importMap map[*types.Package]string
}
const (
goPreamble = gobindPreamble + `// Package main is an autogenerated binder stub for package %[1]s.
//
// autogenerated by gobind -lang=go %[2]s
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "%[1]s.h"
*/
import "C"
`
)
func (g *goGen) genFuncBody(o *types.Func, selectorLHS string) {
sig := o.Type().(*types.Signature)
params := sig.Params()
for i := 0; i < params.Len(); i++ {
p := params.At(i)
pn := "param_" + g.paramName(params, i)
g.genRead("_"+pn, pn, p.Type(), modeTransient)
}
res := sig.Results()
if res.Len() > 2 || res.Len() == 2 && !isErrorType(res.At(1).Type()) {
g.errorf("functions and methods must return either zero or one values, and optionally an error")
return
}
if res.Len() > 0 {
for i := 0; i < res.Len(); i++ {
if i > 0 {
g.Printf(", ")
}
g.Printf("res_%d", i)
}
g.Printf(" := ")
}
g.Printf("%s%s(", selectorLHS, o.Name())
for i := 0; i < params.Len(); i++ {
if i > 0 {
g.Printf(", ")
}
g.Printf("_param_%s", g.paramName(params, i))
}
g.Printf(")\n")
for i := 0; i < res.Len(); i++ {
pn := fmt.Sprintf("res_%d", i)
g.genWrite("_"+pn, pn, res.At(i).Type(), modeRetained)
}
if res.Len() > 0 {
g.Printf("return ")
for i := 0; i < res.Len(); i++ {
if i > 0 {
g.Printf(", ")
}
g.Printf("_res_%d", i)
}
g.Printf("\n")
}
}
func (g *goGen) genWrite(toVar, fromVar string, t types.Type, mode varMode) {
switch t := t.(type) {
case *types.Basic:
switch t.Kind() {
case types.String:
g.Printf("%s := encodeString(%s)\n", toVar, fromVar)
case types.Bool:
g.Printf("var %s C.%s = 0\n", toVar, g.cgoType(t))
g.Printf("if %s { %s = 1 }\n", fromVar, toVar)
default:
g.Printf("%s := C.%s(%s)\n", toVar, g.cgoType(t), fromVar)
}
case *types.Slice:
switch e := t.Elem().(type) {
case *types.Basic:
switch e.Kind() {
case types.Uint8: // Byte.
g.Printf("%s := fromSlice(%s, %v)\n", toVar, fromVar, mode == modeRetained)
default:
g.errorf("unsupported type: %s", t)
}
default:
g.errorf("unsupported type: %s", t)
}
case *types.Pointer:
// TODO(crawshaw): test *int
// TODO(crawshaw): test **Generator
switch t := t.Elem().(type) {
case *types.Named:
g.genToRefNum(toVar, fromVar)
default:
g.errorf("unsupported type %s", t)
}
case *types.Named:
switch u := t.Underlying().(type) {
case *types.Interface, *types.Pointer:
g.genToRefNum(toVar, fromVar)
default:
g.errorf("unsupported, direct named type %s: %s", t, u)
}
default:
g.errorf("unsupported type %s", t)
}
}
// genToRefNum generates Go code for converting a variable to its refnum.
// Note that the nil-check cannot be lifted into seq.ToRefNum, because a nil
// struct pointer does not convert to a nil interface.
func (g *goGen) genToRefNum(toVar, fromVar string) {
g.Printf("var %s C.int32_t = _seq.NullRefNum\n", toVar)
g.Printf("if %s != nil {\n", fromVar)
g.Printf(" %s = C.int32_t(_seq.ToRefNum(%s))\n", toVar, fromVar)
g.Printf("}\n")
}
func (g *goGen) genFuncSignature(o *types.Func, objName string) {
g.Printf("//export proxy%s_%s_%s\n", g.pkgPrefix, objName, o.Name())
g.Printf("func proxy%s_%s_%s(", g.pkgPrefix, objName, o.Name())
if objName != "" {
g.Printf("refnum C.int32_t")
}
sig := o.Type().(*types.Signature)
params := sig.Params()
for i := 0; i < params.Len(); i++ {
if objName != "" || i > 0 {
g.Printf(", ")
}
p := params.At(i)
g.Printf("param_%s C.%s", g.paramName(params, i), g.cgoType(p.Type()))
}
g.Printf(") ")
res := sig.Results()
if res.Len() > 0 {
g.Printf("(")
for i := 0; i < res.Len(); i++ {
if i > 0 {
g.Printf(", ")
}
g.Printf("C.%s", g.cgoType(res.At(i).Type()))
}
g.Printf(") ")
}
g.Printf("{\n")
}
func (g *goGen) paramName(params *types.Tuple, pos int) string {
return basicParamName(params, pos)
}
func (g *goGen) genFunc(o *types.Func) {
if !g.isSigSupported(o.Type()) {
g.Printf("// skipped function %s with unsupported parameter or result types\n", o.Name())
return
}
g.genFuncSignature(o, "")
g.Indent()
g.genFuncBody(o, g.pkgName(g.Pkg))
g.Outdent()
g.Printf("}\n\n")
}
func (g *goGen) genStruct(obj *types.TypeName, T *types.Struct) {
fields := exportedFields(T)
methods := exportedMethodSet(types.NewPointer(obj.Type()))
for _, f := range fields {
if t := f.Type(); !g.isSupported(t) {
g.Printf("// skipped field %s.%s with unsupported type: %s\n\n", obj.Name(), f.Name(), t)
continue
}
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.pkgName(g.Pkg), obj.Name(), f.Name())
g.Outdent()
g.Printf("}\n\n")
g.Printf("//export proxy%s_%s_%s_Get\n", g.pkgPrefix, obj.Name(), f.Name())
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.pkgName(g.Pkg), obj.Name(), f.Name())
g.genWrite("_v", "v", f.Type(), modeRetained)
g.Printf("return _v\n")
g.Outdent()
g.Printf("}\n\n")
}
for _, m := range methods {
if !g.isSigSupported(m.Type()) {
g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", obj.Name(), m.Name())
continue
}
g.genFuncSignature(m, obj.Name())
g.Indent()
g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
g.Printf("v := ref.Get().(*%s%s)\n", g.pkgName(g.Pkg), obj.Name())
g.genFuncBody(m, "v.")
g.Outdent()
g.Printf("}\n\n")
}
// Export constructor for ObjC and Java default no-arg constructors
g.Printf("//export new_%s_%s\n", g.Pkg.Name(), obj.Name())
g.Printf("func new_%s_%s() C.int32_t {\n", g.Pkg.Name(), obj.Name())
g.Indent()
g.Printf("return C.int32_t(_seq.ToRefNum(new(%s%s)))\n", g.pkgName(g.Pkg), obj.Name())
g.Outdent()
g.Printf("}\n")
}
func (g *goGen) genVar(o *types.Var) {
if t := o.Type(); !g.isSupported(t) {
g.Printf("// skipped variable %s with unsupported type %s\n\n", o.Name(), t)
return
}
// TODO(hyangah): non-struct pointer types (*int), struct type.
v := fmt.Sprintf("%s%s", g.pkgName(g.Pkg), o.Name())
// var I int
//
// func var_setI(v int)
g.Printf("//export var_set%s_%s\n", g.pkgPrefix, o.Name())
g.Printf("func var_set%s_%s(v C.%s) {\n", g.pkgPrefix, o.Name(), g.cgoType(o.Type()))
g.Indent()
g.genRead("_v", "v", o.Type(), modeRetained)
g.Printf("%s = _v\n", v)
g.Outdent()
g.Printf("}\n")
// func var_getI() int
g.Printf("//export var_get%s_%s\n", g.pkgPrefix, o.Name())
g.Printf("func var_get%s_%s() C.%s {\n", g.pkgPrefix, o.Name(), g.cgoType(o.Type()))
g.Indent()
g.Printf("v := %s\n", v)
g.genWrite("_v", "v", o.Type(), modeRetained)
g.Printf("return _v\n")
g.Outdent()
g.Printf("}\n")
}
func (g *goGen) genInterface(obj *types.TypeName) {
iface := obj.Type().(*types.Named).Underlying().(*types.Interface)
summary := makeIfaceSummary(iface)
// Define the entry points.
for _, m := range summary.callable {
if !g.isSigSupported(m.Type()) {
g.Printf("// skipped method %s.%s with unsupported parameter or return types\n\n", obj.Name(), m.Name())
continue
}
g.genFuncSignature(m, obj.Name())
g.Indent()
g.Printf("ref := _seq.FromRefNum(int32(refnum))\n")
g.Printf("v := ref.Get().(%s%s)\n", g.pkgName(g.Pkg), obj.Name())
g.genFuncBody(m, "v.")
g.Outdent()
g.Printf("}\n\n")
}
// Define a proxy interface.
if !summary.implementable {
// The interface defines an unexported method or a method that
// uses an unexported type. We cannot generate a proxy object
// for such a type.
return
}
g.Printf("type proxy%s_%s _seq.Ref\n\n", g.pkgPrefix, obj.Name())
g.Printf("func (p *proxy%s_%s) Bind_proxy_refnum__() int32 {\n", g.pkgPrefix, obj.Name())
g.Indent()
g.Printf("return (*_seq.Ref)(p).Bind_IncNum()\n")
g.Outdent()
g.Printf("}\n\n")
for _, m := range summary.callable {
if !g.isSigSupported(m.Type()) {
g.Printf("// skipped method %s.%s with unsupported parameter or result types\n", obj.Name(), m.Name())
continue
}
sig := m.Type().(*types.Signature)
params := sig.Params()
res := sig.Results()
if res.Len() > 2 ||
(res.Len() == 2 && !isErrorType(res.At(1).Type())) {
g.errorf("functions and methods must return either zero or one value, and optionally an error: %s.%s", obj.Name(), m.Name())
continue
}
g.Printf("func (p *proxy%s_%s) %s(", g.pkgPrefix, obj.Name(), m.Name())
for i := 0; i < params.Len(); i++ {
if i > 0 {
g.Printf(", ")
}
g.Printf("param_%s %s", g.paramName(params, i), g.typeString(params.At(i).Type()))
}
g.Printf(") ")
if res.Len() == 1 {
g.Printf("%s", g.typeString(res.At(0).Type()))
} else if res.Len() == 2 {
g.Printf("(%s, error)", g.typeString(res.At(0).Type()))
}
g.Printf(" {\n")
g.Indent()
for i := 0; i < params.Len(); i++ {
pn := "param_" + g.paramName(params, i)
g.genWrite("_"+pn, pn, params.At(i).Type(), modeTransient)
}
if res.Len() > 0 {
g.Printf("res := ")
}
g.Printf("C.cproxy%s_%s_%s(C.int32_t(p.Bind_proxy_refnum__())", g.pkgPrefix, obj.Name(), m.Name())
for i := 0; i < params.Len(); i++ {
g.Printf(", _param_%s", g.paramName(params, i))
}
g.Printf(")\n")
var retName string
if res.Len() > 0 {
if res.Len() == 1 {
T := res.At(0).Type()
g.genRead("_res", "res", T, modeRetained)
retName = "_res"
} else {
var rvs []string
for i := 0; i < res.Len(); i++ {
rv := fmt.Sprintf("res_%d", i)
g.genRead(rv, fmt.Sprintf("res.r%d", i), res.At(i).Type(), modeRetained)
rvs = append(rvs, rv)
}
retName = strings.Join(rvs, ", ")
}
g.Printf("return %s\n", retName)
}
g.Outdent()
g.Printf("}\n\n")
}
}
func (g *goGen) genRead(toVar, fromVar string, typ types.Type, mode varMode) {
switch t := typ.(type) {
case *types.Basic:
switch t.Kind() {
case types.String:
g.Printf("%s := decodeString(%s)\n", toVar, fromVar)
case types.Bool:
g.Printf("%s := %s != 0\n", toVar, fromVar)
default:
g.Printf("%s := %s(%s)\n", toVar, t.Underlying().String(), fromVar)
}
case *types.Slice:
switch e := t.Elem().(type) {
case *types.Basic:
switch e.Kind() {
case types.Uint8: // Byte.
g.Printf("%s := toSlice(%s, %v)\n", toVar, fromVar, mode == modeRetained)
default:
g.errorf("unsupported type: %s", t)
}
default:
g.errorf("unsupported type: %s", t)
}
case *types.Pointer:
switch u := t.Elem().(type) {
case *types.Named:
o := u.Obj()
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("var %s *%s%s\n", toVar, g.pkgName(oPkg), o.Name())
g.Printf("if %s_ref := _seq.FromRefNum(int32(%s)); %s_ref != nil {\n", toVar, fromVar, toVar)
g.Printf(" %s = %s_ref.Get().(*%s%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
g.Printf("}\n")
default:
g.errorf("unsupported pointer type %s", t)
}
case *types.Named:
switch t.Underlying().(type) {
case *types.Interface, *types.Pointer:
hasProxy := true
if iface, ok := t.Underlying().(*types.Interface); ok {
hasProxy = makeIfaceSummary(iface).implementable
}
pkgFirst := typePkgFirstElem(t)
isWrapper := pkgFirst == "Java" || pkgFirst == "ObjC"
o := t.Obj()
oPkg := o.Pkg()
if !isErrorType(t) && !g.validPkg(oPkg) && !isWrapper {
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 < 0 { // go object \n", fromVar)
g.Printf(" %s = %s_ref.Get().(%s%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
if hasProxy {
g.Printf(" } else { // foreign object \n")
if isWrapper {
var clsName string
switch pkgFirst {
case "Java":
clsName = flattenName(classNameFor(t))
case "ObjC":
clsName = t.Obj().Name()
}
g.Printf(" %s = (*proxy_class_%s)(%s_ref)\n", toVar, clsName, toVar)
} else {
g.Printf(" %s = (*proxy%s_%s)(%s_ref)\n", toVar, pkgPrefix(oPkg), o.Name(), toVar)
}
}
g.Printf(" }\n")
g.Printf("}\n")
default:
g.errorf("unsupported named type %s", t)
}
default:
g.errorf("unsupported type: %s", typ)
}
}
func (g *goGen) typeString(typ types.Type) string {
pkg := g.Pkg
switch t := typ.(type) {
case *types.Named:
obj := t.Obj()
if obj.Pkg() == nil { // e.g. error type is *types.Named.
return types.TypeString(typ, types.RelativeTo(pkg))
}
oPkg := obj.Pkg()
if !g.validPkg(oPkg) && !isWrapperType(t) {
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", g.pkgName(oPkg), types.TypeString(typ, types.RelativeTo(oPkg)))
default:
g.errorf("unsupported named type %s / %T", t, t)
}
case *types.Pointer:
switch t := t.Elem().(type) {
case *types.Named:
return fmt.Sprintf("*%s", g.typeString(t))
default:
g.errorf("not yet supported, pointer type %s / %T", t, t)
}
default:
return types.TypeString(typ, types.RelativeTo(pkg))
}
return ""
}
// genPreamble generates the preamble. It is generated after everything
// else, where we know which bound packages to import.
func (g *goGen) genPreamble() {
pkgName := ""
pkgPath := ""
if g.Pkg != nil {
pkgName = g.Pkg.Name()
pkgPath = g.Pkg.Path()
} else {
pkgName = "universe"
}
g.Printf(goPreamble, pkgName, pkgPath)
g.Printf("import (\n")
g.Indent()
g.Printf("_seq \"golang.org/x/mobile/bind/seq\"\n")
for _, imp := range g.imports {
g.Printf("%s\n", imp)
}
g.Outdent()
g.Printf(")\n\n")
}
func (g *goGen) gen() error {
g.importNames = make(map[string]struct{})
g.importMap = make(map[*types.Package]string)
// 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)
}
for _, intf := range g.interfaces {
g.genInterface(intf.obj)
}
for _, v := range g.vars {
g.genVar(v)
}
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 returns the package name and adds the package to the list of
// imports.
func (g *goGen) pkgName(pkg *types.Package) string {
// The error type has no package
if pkg == nil {
return ""
}
if name, exists := g.importMap[pkg]; exists {
return name + "."
}
i := 0
pname := pkg.Name()
name := pkg.Name()
for {
if _, exists := g.importNames[name]; !exists {
g.importNames[name] = struct{}{}
g.importMap[pkg] = name
var imp string
if pname != name {
imp = fmt.Sprintf("%s %q", name, pkg.Path())
} else {
imp = fmt.Sprintf("%q", pkg.Path())
}
g.imports = append(g.imports, imp)
break
}
i++
name = fmt.Sprintf("%s_%d", pname, i)
}
g.importMap[pkg] = name
return name + "."
}

1732
bind/genjava.go Normal file

File diff suppressed because it is too large Load diff

1428
bind/genobjc.go Normal file

File diff suppressed because it is too large Load diff

754
bind/genobjcw.go Normal file
View file

@ -0,0 +1,754 @@
// 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 bind
import (
"path"
"strings"
"golang.org/x/mobile/internal/importers/objc"
)
type (
// ObjCWrapper generates Go and C stubs for ObjC interfaces and protocols.
ObjcWrapper struct {
*Printer
imported map[string]*objc.Named
// The list of ObjC types.
types []*objc.Named
// The list of Go package paths with ObjC wrappers.
pkgNames []string
modules []string
// For each ObjC module, the list of ObjC types within.
modMap map[string][]*objc.Named
// For each module/name Go package path, the ObjC type
// with static functions or constants.
typePkgs map[string]*objc.Named
// supers is the map of types that need Super methods.
supers map[string]struct{}
}
)
// Init initializes the ObjC types wrapper generator. Types is the
// list of types to wrap, genNames the list of generated type names.
func (g *ObjcWrapper) Init(types []*objc.Named, genNames []string) {
g.supers = make(map[string]struct{})
for _, s := range genNames {
g.supers[s] = struct{}{}
}
g.types = types
g.imported = make(map[string]*objc.Named)
g.modMap = make(map[string][]*objc.Named)
g.typePkgs = make(map[string]*objc.Named)
pkgSet := make(map[string]struct{})
for _, n := range types {
g.imported[n.GoName] = n
typePkg := n.Module + "/" + n.GoName
g.typePkgs[typePkg] = n
if !n.Generated {
if _, exists := g.modMap[n.Module]; !exists {
g.modules = append(g.modules, n.Module)
}
}
g.modMap[n.Module] = append(g.modMap[n.Module], n)
if _, exists := pkgSet[n.Module]; !exists {
pkgSet[n.Module] = struct{}{}
g.pkgNames = append(g.pkgNames, n.Module)
}
g.pkgNames = append(g.pkgNames, typePkg)
}
}
func (g *ObjcWrapper) GenM() {
g.Printf(gobindPreamble)
// For objc_msgSend* functions.
g.Printf("@import ObjectiveC.message;\n")
g.Printf("#include \"seq.h\"\n")
g.Printf("#include \"interfaces.h\"\n\n")
for _, n := range g.types {
g.genM(n)
}
g.Printf("\n")
for _, n := range g.types {
for _, f := range n.AllMethods {
if !g.isFuncSupported(f) {
continue
}
g.genCFuncDecl("cproxy", n.GoName, f)
g.genCFuncBody(n, f, false)
if _, exists := g.supers[n.GoName]; exists {
g.genCFuncDecl("csuper", n.GoName, f)
g.genCFuncBody(n, f, true)
}
}
}
}
func (g *ObjcWrapper) genCFuncBody(n *objc.Named, f *objc.Func, super bool) {
g.Printf(" {\n")
g.Indent()
if !f.Static {
g.Printf("%s _this = go_seq_from_refnum(this).obj;\n", n.ObjcType())
}
var errParam *objc.Param
for i, a := range f.Params {
if i == len(f.Params)-1 && g.isErrorType(a.Type) {
errParam = a
break
}
g.genCToObjC(a.Name, a.Type, modeTransient)
}
if errParam != nil {
g.Printf("NSError *%s = nil;\n", errParam.Name)
}
if f.Constructor {
g.Printf("%s _this = [%s alloc];\n", n.ObjcType(), n.Name)
}
if super {
g.Printf("struct objc_super _super = {\n")
g.Printf(" .receiver = _this,\n")
g.Printf(" .super_class = class_getSuperclass([%s class]),\n", n.Name)
g.Printf("};\n")
}
retType := "void"
if f.Ret != nil {
retType = g.objcType(f.Ret)
g.Printf("%s res = ", retType)
}
// There is no direct way to send a message to a class' super
// class from outside the class itself. Use objc_msgSendSuper instead
// which is what the compiler uses itself. To keep us honest and to exercise
// the code paths more use objc_msgSend for regular calls as well.
//
// A regular call looks like this:
//
// res = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSend)(_this, @selector(...), <arguments>)
//
// a call to super looks like this:
//
// ret = ((<return type> (*)(id, SEL, <argument_types>))objc_msgSendSuper)(<struct objc_super>, <arguments>)
if f.Ret != nil {
switch f.Ret.Kind {
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:
default:
// If support for struct results is added, objc_msgSend_stret must be used
panic("unsupported type kind - use objc_msgSend_stret?")
}
}
g.Printf("((%s (*)(", retType)
if super {
g.Printf("struct objc_super *")
} else {
g.Printf("id")
}
g.Printf(", SEL")
for _, a := range f.Params {
g.Printf(", %s", g.objcType(a.Type))
}
g.Printf("))")
if super {
g.Printf("objc_msgSendSuper")
} else {
g.Printf("objc_msgSend")
}
g.Printf(")(")
if f.Static && !f.Constructor {
g.Printf("[%s class]", n.Name)
} else {
if super {
g.Printf("&_super")
} else {
g.Printf("_this")
}
}
g.Printf(", @selector(%s)", f.Sig)
for _, a := range f.Params {
arg := "_" + a.Name
if a == errParam {
arg = "&" + a.Name
}
g.Printf(", %s", arg)
}
g.Printf(");\n")
if errParam != nil {
g.Printf("NSError *_%s = nil;\n", errParam.Name)
if f.Ret != nil {
g.Printf("if (!res && %s != nil) {\n", errParam.Name)
} else {
g.Printf("if (%s != nil) {\n", errParam.Name)
}
g.Printf(" _%[1]s = %[1]s;\n", errParam.Name)
g.Printf("}\n")
g.genObjCToC("_"+errParam.Name, g.errType(), modeRetained)
}
ret := f.Ret
if ret != nil && ret.Kind == objc.Bool && errParam != nil {
ret = nil
}
if ret != nil {
g.genObjCToC("res", ret, modeRetained)
}
switch {
case ret != nil && errParam != nil:
stype := strings.Replace(g.cType(ret), " ", "_", -1)
g.Printf("ret_%s _sres = {_res, __%s};\n", stype, errParam.Name)
g.Printf("return _sres;\n")
case ret != nil:
g.Printf("return _res;\n")
case errParam != nil:
g.Printf("return __%s;\n", errParam.Name)
}
g.Outdent()
g.Printf("}\n\n")
}
func (_ *ObjcWrapper) errType() *objc.Type {
return &objc.Type{Kind: objc.Class, Name: "NSError"}
}
func (g *ObjcWrapper) genM(n *objc.Named) {
for _, f := range n.Funcs {
if !g.isFuncSupported(f) {
continue
}
g.genCFuncDecl("cproxy", n.GoName, f)
g.genCFuncBody(n, f, false)
}
}
func (g *ObjcWrapper) GenH() {
g.Printf(gobindPreamble)
g.Printf("#include \"seq.h\"\n\n")
for _, m := range g.modules {
g.Printf("@import %s;\n", m)
}
// Include header files for generated types
for _, n := range g.pkgNames {
hasGen := false
for _, t := range g.modMap[n] {
if t.Generated {
hasGen = true
break
}
}
if hasGen {
g.Printf("#import %q\n", n+".objc.h")
}
}
for _, tn := range []string{"int", "nstring", "nbyteslice", "long", "unsigned long", "short", "unsigned short", "bool", "char", "unsigned char", "float", "double"} {
sn := strings.Replace(tn, " ", "_", -1)
g.Printf("typedef struct ret_%s {\n", sn)
g.Printf(" %s res;\n", tn)
g.Printf(" int err;\n")
g.Printf("} ret_%s;\n", sn)
}
g.Printf("\n")
for _, n := range g.types {
for _, f := range n.AllMethods {
if !g.isFuncSupported(f) {
continue
}
g.Printf("extern ")
g.genCFuncDecl("cproxy", n.GoName, f)
g.Printf(";\n")
if _, exists := g.supers[n.GoName]; exists {
g.Printf("extern ")
g.genCFuncDecl("csuper", n.GoName, f)
g.Printf(";\n")
}
}
}
for _, cls := range g.types {
g.genH(cls)
}
}
func (g *ObjcWrapper) genH(n *objc.Named) {
for _, f := range n.Funcs {
if !g.isFuncSupported(f) {
continue
}
g.Printf("extern ")
g.genCFuncDecl("cproxy", n.GoName, f)
g.Printf(";\n")
}
}
func (g *ObjcWrapper) genCFuncDecl(prefix, name string, f *objc.Func) {
returnsErr := len(f.Params) > 0 && g.isErrorType(f.Params[len(f.Params)-1].Type)
ret := f.Ret
if ret != nil && returnsErr && ret.Kind == objc.Bool {
ret = nil
}
switch {
case ret != nil && returnsErr:
g.Printf("ret_%s", strings.Replace(g.cType(ret), " ", "_", -1))
case ret != nil:
g.Printf("%s", g.cType(ret))
case returnsErr:
g.Printf("int")
default:
g.Printf("void")
}
g.Printf(" %s", prefix)
if f.Static {
g.Printf("_s")
}
g.Printf("_%s_%s(", name, f.GoName)
if !f.Static {
g.Printf("int this")
}
for i, p := range f.Params {
if i == len(f.Params)-1 && returnsErr {
break
}
if !f.Static || i > 0 {
g.Printf(", ")
}
g.Printf("%s %s", g.cType(p.Type), p.Name)
}
g.Printf(")")
}
func (g *ObjcWrapper) GenGo() {
g.Printf(gobindPreamble)
g.Printf("package main\n\n")
g.Printf("// #include \"interfaces.h\"\n")
g.Printf("import \"C\"\n\n")
g.Printf("import \"ObjC\"\n")
g.Printf("import _seq \"golang.org/x/mobile/bind/seq\"\n")
for _, n := range g.types {
for _, f := range n.Funcs {
if g.isFuncSupported(f) {
pkgName := n.Module + "/" + n.GoName
g.Printf("import %q\n", "ObjC/"+pkgName)
break
}
}
}
g.Printf("\n")
g.Printf("type proxy interface { Bind_proxy_refnum__() int32 }\n\n")
g.Printf("// Suppress unused package error\n\n")
g.Printf("var _ = _seq.FromRefNum\n")
g.Printf("const _ = ObjC.Dummy\n\n")
for _, n := range g.types {
g.genGo(n)
}
}
func (g *ObjcWrapper) genGo(n *objc.Named) {
g.Printf("func init() {\n")
g.Indent()
for _, f := range n.Funcs {
if !g.isFuncSupported(f) {
continue
}
g.Printf("%s.%s = func", n.GoName, f.GoName)
g.genFuncDecl(false, f)
g.genFuncBody(n, f, "cproxy")
}
g.Outdent()
g.Printf("}\n\n")
g.Printf("type proxy_class_%s _seq.Ref\n\n", n.GoName)
g.Printf("func (p *proxy_class_%s) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }\n\n", n.GoName)
for _, f := range n.AllMethods {
if !g.isFuncSupported(f) {
continue
}
g.Printf("func (p *proxy_class_%s) %s", n.GoName, f.GoName)
g.genFuncDecl(false, f)
g.genFuncBody(n, f, "cproxy")
}
if _, exists := g.supers[n.GoName]; exists {
g.Printf("func (p *proxy_class_%s) Super() ObjC.%s {\n", n.GoName, n.Module+"_"+n.GoName)
g.Printf(" return &super_%s{p}\n", n.GoName)
g.Printf("}\n\n")
g.Printf("type super_%s struct {*proxy_class_%[1]s}\n\n", n.GoName)
for _, f := range n.AllMethods {
if !g.isFuncSupported(f) {
continue
}
g.Printf("func (p *super_%s) %s", n.GoName, f.GoName)
g.genFuncDecl(false, f)
g.genFuncBody(n, f, "csuper")
}
}
}
func (g *ObjcWrapper) genFuncBody(n *objc.Named, f *objc.Func, prefix string) {
g.Printf(" {\n")
g.Indent()
var errParam *objc.Param
for i, a := range f.Params {
if i == len(f.Params)-1 && g.isErrorType(a.Type) {
errParam = a
break
}
g.genWrite(a)
}
ret := f.Ret
if ret != nil && errParam != nil && ret.Kind == objc.Bool {
ret = nil
}
if ret != nil || errParam != nil {
g.Printf("res := ")
}
g.Printf("C.%s", prefix)
if f.Static {
g.Printf("_s")
}
g.Printf("_%s_%s(", n.GoName, f.GoName)
if !f.Static {
g.Printf("C.int(p.Bind_proxy_refnum__())")
}
for i, a := range f.Params {
if a == errParam {
break
}
if !f.Static || i > 0 {
g.Printf(", ")
}
g.Printf("_%s", a.Name)
}
g.Printf(")\n")
switch {
case ret != nil && errParam != nil:
g.genRead("_res", "res.res", ret)
g.genRefRead("_"+errParam.Name, "res.err", "error", "proxy_error")
g.Printf("return _res, _%s\n", errParam.Name)
case ret != nil:
g.genRead("_res", "res", ret)
g.Printf("return _res\n")
case errParam != nil:
g.genRefRead("_"+errParam.Name, "res", "error", "proxy_error")
g.Printf("return _%s\n", errParam.Name)
}
g.Outdent()
g.Printf("}\n\n")
}
func (g *ObjcWrapper) genCToObjC(name string, t *objc.Type, mode varMode) {
switch t.Kind {
case objc.String:
g.Printf("NSString *_%s = go_seq_to_objc_string(%s);\n", name, name)
case objc.Bool:
g.Printf("BOOL _%s = %s ? YES : NO;\n", name, name)
case objc.Data:
g.Printf("NSData *_%s = go_seq_to_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained))
case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
g.Printf("%s _%s = (%s)%s;\n", g.objcType(t), name, g.objcType(t), name)
case objc.Class, objc.Protocol:
g.Printf("GoSeqRef* %s_ref = go_seq_from_refnum(%s);\n", name, name)
g.Printf("%s _%s;\n", g.objcType(t), name)
g.Printf("if (%s_ref != NULL) {\n", name)
g.Printf(" _%s = %s_ref.obj;\n", name, name)
g.Printf("}\n")
default:
panic("invalid kind")
}
}
func (g *ObjcWrapper) genObjCToC(name string, t *objc.Type, mode varMode) {
switch t.Kind {
case objc.String:
g.Printf("nstring _%s = go_seq_from_objc_string(%s);\n", name, name)
case objc.Data:
g.Printf("nbyteslice _%s = go_seq_from_objc_bytearray(%s, %d);\n", name, name, toCFlag(mode == modeRetained))
case objc.Bool, objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
g.Printf("%s _%s = (%s)%s;\n", g.cType(t), name, g.cType(t), name)
case objc.Protocol, objc.Class:
g.Printf("int _%s = go_seq_to_refnum(%s);\n", name, name)
default:
panic("invalid kind")
}
}
func (g *ObjcWrapper) genWrite(a *objc.Param) {
switch a.Type.Kind {
case objc.String:
g.Printf("_%s := encodeString(%s)\n", a.Name, a.Name)
case objc.Data:
g.Printf("_%s := fromSlice(%s, false)\n", a.Name, a.Name)
case objc.Bool:
g.Printf("_%s := %s(0)\n", a.Name, g.cgoType(a.Type))
g.Printf("if %s {\n", a.Name)
g.Printf(" _%s = %s(1)\n", a.Name, g.cgoType(a.Type))
g.Printf("}\n")
case objc.Int, objc.Uint, objc.Short, objc.Ushort, objc.Char, objc.Uchar, objc.Float, objc.Double:
g.Printf("_%s := %s(%s)\n", a.Name, g.cgoType(a.Type), a.Name)
case objc.Protocol, objc.Class:
g.Printf("var _%s %s = _seq.NullRefNum\n", a.Name, g.cgoType(a.Type))
g.Printf("if %s != nil {\n", a.Name)
g.Printf(" _%s = %s(_seq.ToRefNum(%s))\n", a.Name, g.cgoType(a.Type), a.Name)
g.Printf("}\n")
default:
panic("invalid kind")
}
}
func (g *ObjcWrapper) genRead(to, from string, t *objc.Type) {
switch t.Kind {
case objc.Int, objc.Uint, objc.Uchar, objc.Short, objc.Ushort, objc.Char, objc.Float, objc.Double:
g.Printf("%s := %s(%s)\n", to, g.goType(t, false), from)
case objc.Bool:
g.Printf("%s := %s != 0\n", to, from)
case objc.String:
g.Printf("%s := decodeString(%s)\n", to, from)
case objc.Data:
g.Printf("%s := toSlice(%s, true)\n", to, from)
case objc.Protocol, objc.Class:
var proxyName string
if n := g.lookupImported(t); n != nil {
proxyName = "proxy_class_" + n.GoName
}
g.genRefRead(to, from, g.goType(t, false), proxyName)
default:
panic("invalid kind")
}
}
func (g *ObjcWrapper) genRefRead(to, from string, intfName, proxyName string) {
g.Printf("var %s %s\n", to, intfName)
g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", to, from)
g.Printf("if %s_ref != nil {\n", to)
g.Printf(" if %s < 0 { // go object\n", from)
g.Printf(" %s = %s_ref.Get().(%s)\n", to, to, intfName)
if proxyName != "" {
g.Printf(" } else { // foreign object\n")
g.Printf(" %s = (*%s)(%s_ref)\n", to, proxyName, to)
}
g.Printf(" }\n")
g.Printf("}\n")
}
// Packages return the list of Go packages to be generated.
func (g *ObjcWrapper) Packages() []string {
return g.pkgNames
}
func (g *ObjcWrapper) GenPackage(idx int) {
pkg := g.pkgNames[idx]
g.Printf(gobindPreamble)
g.Printf("package %s\n\n", path.Base(pkg))
g.Printf("import \"ObjC\"\n\n")
g.Printf("const _ = ObjC.Dummy\n\n")
for _, n := range g.modMap[pkg] {
g.Printf("type %s ObjC.%s\n", n.GoName, n.Module+"_"+n.GoName)
}
if n, ok := g.typePkgs[pkg]; ok {
g.Printf("var (\n")
g.Indent()
// Functions
for _, f := range n.Funcs {
if !g.isFuncSupported(f) {
continue
}
g.Printf("%s func", f.GoName)
g.genFuncDecl(false, f)
g.Printf("\n")
}
g.Outdent()
g.Printf(")\n\n")
}
}
func (g *ObjcWrapper) GenInterfaces() {
g.Printf(gobindPreamble)
g.Printf("package ObjC\n\n")
g.Printf("// Used to silence this package not used errors\n")
g.Printf("const Dummy = 0\n\n")
for _, n := range g.types {
g.genInterface(n)
}
}
func (g *ObjcWrapper) genInterface(n *objc.Named) {
g.Printf("type %s interface {\n", n.Module+"_"+n.GoName)
g.Indent()
// Methods
for _, f := range n.AllMethods {
if !g.isFuncSupported(f) {
continue
}
g.Printf("%s", f.GoName)
g.genFuncDecl(true, f)
g.Printf("\n")
}
if _, exists := g.supers[n.GoName]; exists {
g.Printf("Super() %s\n", n.Module+"_"+n.GoName)
}
g.Outdent()
g.Printf("}\n\n")
}
func (g *ObjcWrapper) genFuncDecl(local bool, f *objc.Func) {
var returnsErr bool
g.Printf("(")
for i, p := range f.Params {
if i == len(f.Params)-1 && g.isErrorType(p.Type) {
returnsErr = true
break
}
if i > 0 {
g.Printf(", ")
}
g.Printf("%s %s", p.Name, g.goType(p.Type, local))
}
g.Printf(")")
if f.Ret != nil || returnsErr {
ret := f.Ret
if ret.Kind == objc.Bool && returnsErr {
// Skip the bool result and use the error results.
ret = nil
}
if ret != nil {
g.Printf(" (%s", g.goType(f.Ret, local))
if returnsErr {
g.Printf(", error")
}
g.Printf(")")
} else {
g.Printf(" error")
}
}
}
func (g *ObjcWrapper) isFuncSupported(f *objc.Func) bool {
for i, p := range f.Params {
if !g.isSupported(p.Type) {
if i < len(f.Params)-1 || !g.isErrorType(p.Type) {
return false
}
}
}
if f.Ret != nil {
return g.isSupported(f.Ret)
}
return true
}
func (g *ObjcWrapper) isErrorType(t *objc.Type) bool {
// Must be a NSError ** type
return t.Kind == objc.Class && t.Indirect && t.Name == "NSError"
}
func (g *ObjcWrapper) isSupported(t *objc.Type) bool {
if t.Indirect {
return false
}
switch t.Kind {
case objc.Unknown:
return false
case objc.Protocol:
// TODO: support inout parameters.
return !strings.HasSuffix(t.Decl, " *")
case objc.Class:
return t.Name != "SEL" && t.Name != "void"
default:
return true
}
}
func (g *ObjcWrapper) cgoType(t *objc.Type) string {
switch t.Kind {
case objc.Uint:
return "C.ulong"
case objc.Ushort:
return "C.ushort"
case objc.Uchar:
return "C.uchar"
default:
return "C." + g.cType(t)
}
}
func (g *ObjcWrapper) cType(t *objc.Type) string {
switch t.Kind {
case objc.Protocol, objc.Class:
return "int"
case objc.String:
return "nstring"
case objc.Data:
return "nbyteslice"
case objc.Int:
return "long"
case objc.Uint:
return "unsigned long"
case objc.Short:
return "short"
case objc.Ushort:
return "unsigned short"
case objc.Bool:
return "char"
case objc.Char:
return "char"
case objc.Uchar:
return "unsigned char"
case objc.Float:
return "float"
case objc.Double:
return "double"
default:
panic("invalid kind")
}
}
func (g *ObjcWrapper) objcType(t *objc.Type) string {
return t.Decl
}
func (g *ObjcWrapper) lookupImported(t *objc.Type) *objc.Named {
var mangled string
switch t.Kind {
case objc.Class:
mangled = t.Name + "C"
case objc.Protocol:
mangled = t.Name + "P"
default:
panic("invalid type kind")
}
if n, exists := g.imported[mangled]; exists {
return n
}
return g.imported[t.Name]
}
func (g *ObjcWrapper) goType(t *objc.Type, local bool) string {
switch t.Kind {
case objc.String:
return "string"
case objc.Data:
return "[]byte"
case objc.Int:
return "int"
case objc.Uint:
return "uint"
case objc.Short:
return "int16"
case objc.Ushort:
return "uint16"
case objc.Bool:
return "bool"
case objc.Char:
return "byte"
case objc.Uchar:
return "uint8"
case objc.Float:
return "float32"
case objc.Double:
return "float64"
case objc.Protocol, objc.Class:
var n *objc.Named
n = g.lookupImported(t)
name := n.Module + "_" + n.GoName
if !local {
name = "ObjC." + name
}
return name
default:
panic("invalid kind")
}
}

9
bind/implicit.go Normal file
View file

@ -0,0 +1,9 @@
// This file imports implicit dependencies required by generated code.
//go:build mobile_implicit
package bind
import (
_ "golang.org/x/mobile/bind/seq"
)

157
bind/java/ClassesTest.java Normal file
View file

@ -0,0 +1,157 @@
// 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 go;
import android.test.InstrumentationTestCase;
import android.test.MoreAsserts;
import java.io.InputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import javapkg.Javapkg;
import javapkg.I;
import javapkg.GoObject;
import javapkg.GoRunnable;
import javapkg.GoSubset;
import javapkg.GoInputStream;
import javapkg.GoArrayList;
public class ClassesTest extends InstrumentationTestCase {
public void testConst() {
assertEquals("const Float", Float.MIN_VALUE, Javapkg.floatMin());
assertEquals("const String", java.util.jar.JarFile.MANIFEST_NAME, Javapkg.manifestName());
assertEquals("const Int", 7, Integer.SIZE, Javapkg.integerBytes());
}
public void testFunction() {
Javapkg.systemCurrentTimeMillis();
}
public void testMethod() {
try {
assertEquals("Integer.decode", 0xff, Javapkg.integerDecode("0xff"));
} catch (Exception e) {
throw new RuntimeException(e);
}
Exception exc = null;
try {
Javapkg.integerDecode("obviously wrong");
} catch (Exception e) {
exc = e;
}
assertNotNull("IntegerDecode Exception", exc);
}
public void testOverloadedMethod() {
try {
assertEquals("Integer.parseInt", 0xc4, Javapkg.integerParseInt("c4", 16));
} catch (Exception e) {
throw new RuntimeException(e);
}
Exception exc = null;
try {
Javapkg.integerParseInt("wrong", 16);
} catch (Exception e) {
exc = e;
}
assertNotNull("integerParseInt Exception", exc);
assertEquals("Integer.valueOf", 42, Javapkg.integerValueOf(42));
}
public void testException() {
Exception exc = null;
try {
Javapkg.provokeRuntimeException();
} catch (Exception e) {
exc = e;
}
assertNotNull("RuntimeException", exc);
}
public void testField() {
GoRunnable r = new GoRunnable();
String f = r.getField();
}
public void testGoObject() {
Runnable r = new GoRunnable();
r.run();
assertEquals("GoRunnable.toString", r.toString(), Javapkg.ToStringPrefix);
Runnable r2 = ((GoRunnable)r).getThis();
assertTrue("GoObject.this", r == r2);
Object o = new GoObject();
assertEquals("GoObject hashCode", 42, o.hashCode());
Object o2 = Javapkg.constructGoObject();
assertEquals("GoObject hashCode", 42, o2.hashCode());
assertTrue("GoObject.toString", o.toString().startsWith(Javapkg.ToStringPrefix));
Javapkg.runRunnable(r);
final boolean[] ran = new boolean[1];
Runnable r3 = new Runnable(){
@Override public void run() {
ran[0] = true;
}
};
Javapkg.runRunnable(r3);
assertTrue("RunRunnable", ran[0]);
assertTrue("RunnableRoundtrip Java", r3 == Javapkg.runnableRoundtrip(r3));
assertTrue("RunnableRoundtrip Go", r == Javapkg.runnableRoundtrip(r));
Runnable r5 = Javapkg.constructGoRunnable();
r5.run();
}
public void testTypedException() {
InputStream is = new GoInputStream();
Exception exc = null;
try {
is.read();
} catch (IOException e) {
exc = e;
}
assertNotNull("IOException", exc);
assertEquals("IOException message", Javapkg.IOExceptionMessage, exc.getMessage());
}
public void testInnerClass() {
Character.Subset s = new Character.Subset(""){};
Character.Subset s2 = new GoSubset("");
Javapkg.callSubset(s);
Javapkg.callSubset(s2);
}
public void testNew() {
Object o = Javapkg.newJavaObject();
assertTrue("new Object()", o != null);
Integer i = Javapkg.newJavaInteger();
assertEquals("new Integer(42)", 42, i.intValue());
}
private static class InterfaceRunnable implements I, Runnable {
@Override public void run() {
}
}
public void testCast() {
Runnable r1 = new GoRunnable();
Runnable r1c = Javapkg.castRunnable((Object)r1);
assertTrue("Casting Go object", r1c != null);
Runnable r2 = new Runnable() {
@Override public void run() {
}
};
Runnable r2c = Javapkg.castRunnable((Object)r2);
assertTrue("Casting Java object", r2c != null);
Runnable r3c = Javapkg.castInterface(new InterfaceRunnable());
assertTrue("Casting Go interface implementation", r3c != null);
Runnable r4c = Javapkg.castRunnable(new Object());
assertTrue("Invalid cast", r4c == null);
}
public void testUnwrap() {
GoArrayList l = new GoArrayList();
Javapkg.unwrapGoArrayList(l);
}
}

View file

@ -0,0 +1,15 @@
// 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 go;
import android.test.InstrumentationTestCase;
import org.golang.custompkg.testpkg.Testpkg;
public class CustomPkgTest extends InstrumentationTestCase {
public void testHi() {
Testpkg.hi();
}
}

400
bind/java/Seq.java Normal file
View file

@ -0,0 +1,400 @@
// Copyright 2014 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 go;
import android.content.Context;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import go.Universe;
// Seq is a sequence of machine-dependent encoded values.
// Used by automatically generated language bindings to talk to Go.
public class Seq {
private static Logger log = Logger.getLogger("GoSeq");
// also known to bind/seq/ref.go and bind/objc/seq_darwin.m
private static final int NULL_REFNUM = 41;
// use single Ref for null Object
public static final Ref nullRef = new Ref(NULL_REFNUM, null);
// The singleton GoRefQueue
private static final GoRefQueue goRefQueue = new GoRefQueue();
static {
System.loadLibrary("gojni");
init();
Universe.touch();
}
// setContext sets the context in the go-library to be used in RunOnJvm.
public static void setContext(Context context) {
setContext((java.lang.Object)context);
}
private static native void init();
// Empty method to run class initializer
public static void touch() {}
private Seq() {
}
// ctx is an android.context.Context.
static native void setContext(java.lang.Object ctx);
public static void incRefnum(int refnum) {
tracker.incRefnum(refnum);
}
// incRef increments the reference count of Java objects.
// For proxies for Go objects, it calls into the Proxy method
// incRefnum() to make sure the Go reference count is positive
// even if the Proxy is garbage collected and its Ref is finalized.
public static int incRef(Object o) {
return tracker.inc(o);
}
public static int incGoObjectRef(GoObject o) {
return o.incRefnum();
}
// trackGoRef tracks a Go reference and decrements its refcount
// when the given GoObject wrapper is garbage collected.
//
// TODO(crawshaw): We could cut down allocations for frequently
// sent Go objects by maintaining a map to weak references. This
// however, would require allocating two objects per reference
// instead of one. It also introduces weak references, the bane
// of any Java debugging session.
//
// When we have real code, examine the tradeoffs.
public static void trackGoRef(int refnum, GoObject obj) {
if (refnum > 0) {
throw new RuntimeException("trackGoRef called with Java refnum " + refnum);
}
goRefQueue.track(refnum, obj);
}
public static Ref getRef(int refnum) {
return tracker.get(refnum);
}
// Increment the Go reference count before sending over a refnum.
// The ref parameter is only used to make sure the referenced
// object is not garbage collected before Go increments the
// count. It's the equivalent of Go's runtime.KeepAlive.
public static native void incGoRef(int refnum, GoObject ref);
// Informs the Go ref tracker that Java is done with this refnum.
static native void destroyRef(int refnum);
// decRef is called from seq.FinalizeRef
static void decRef(int refnum) {
tracker.dec(refnum);
}
// A GoObject is a Java class implemented in Go. When a GoObject
// is passed to Go, it is wrapped in a Go proxy, to make it behave
// the same as passing a regular Java class.
public interface GoObject {
// Increment refcount and return the refnum of the proxy.
//
// The Go reference count need to be bumped while the
// refnum is passed to Go, to avoid finalizing and
// invalidating it before being translated on the Go side.
int incRefnum();
}
// A Proxy is a Java object that proxies a Go object. Proxies, unlike
// GoObjects, are unwrapped to their Go counterpart when deserialized
// in Go.
public interface Proxy extends GoObject {}
// A Ref represents an instance of a Java object passed back and forth
// across the language boundary.
public static final class Ref {
public final int refnum;
private int refcnt; // Track how many times sent to Go.
public final Object obj; // The referenced Java obj.
Ref(int refnum, Object o) {
if (refnum < 0) {
throw new RuntimeException("Ref instantiated with a Go refnum " + refnum);
}
this.refnum = refnum;
this.refcnt = 0;
this.obj = o;
}
void inc() {
// Count how many times this ref's Java object is passed to Go.
if (refcnt == Integer.MAX_VALUE) {
throw new RuntimeException("refnum " + refnum + " overflow");
}
refcnt++;
}
}
static final RefTracker tracker = new RefTracker();
static final class RefTracker {
private static final int REF_OFFSET = 42;
// Next Java object reference number.
//
// Reference numbers are positive for Java objects,
// and start, arbitrarily at a different offset to Go
// to make debugging by reading Seq hex a little easier.
private int next = REF_OFFSET; // next Java object ref
// Java objects that have been passed to Go. refnum -> Ref
// The Ref obj field is non-null.
// This map pins Java objects so they don't get GCed while the
// only reference to them is held by Go code.
private final RefMap javaObjs = new RefMap();
// Java objects to refnum
private final IdentityHashMap<Object, Integer> javaRefs = new IdentityHashMap<>();
// inc increments the reference count of a Java object when it
// is sent to Go. inc returns the refnum for the object.
synchronized int inc(Object o) {
if (o == null) {
return NULL_REFNUM;
}
if (o instanceof Proxy) {
return ((Proxy)o).incRefnum();
}
Integer refnumObj = javaRefs.get(o);
if (refnumObj == null) {
if (next == Integer.MAX_VALUE) {
throw new RuntimeException("createRef overflow for " + o);
}
refnumObj = next++;
javaRefs.put(o, refnumObj);
}
int refnum = refnumObj;
Ref ref = javaObjs.get(refnum);
if (ref == null) {
ref = new Ref(refnum, o);
javaObjs.put(refnum, ref);
}
ref.inc();
return refnum;
}
synchronized void incRefnum(int refnum) {
Ref ref = javaObjs.get(refnum);
if (ref == null) {
throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
}
ref.inc();
}
// dec decrements the reference count of a Java object when
// Go signals a corresponding proxy object is finalized.
// If the count reaches zero, the Java object is removed
// from the javaObjs map.
synchronized void dec(int refnum) {
if (refnum <= 0) {
// We don't keep track of the Go object.
// This must not happen.
log.severe("dec request for Go object "+ refnum);
return;
}
if (refnum == Seq.nullRef.refnum) {
return;
}
// Java objects are removed on request of Go.
Ref obj = javaObjs.get(refnum);
if (obj == null) {
throw new RuntimeException("referenced Java object is not found: refnum="+refnum);
}
obj.refcnt--;
if (obj.refcnt <= 0) {
javaObjs.remove(refnum);
javaRefs.remove(obj.obj);
}
}
// get returns an existing Ref to a Java object.
synchronized Ref get(int refnum) {
if (refnum < 0) {
throw new RuntimeException("ref called with Go refnum " + refnum);
}
if (refnum == NULL_REFNUM) {
return nullRef;
}
Ref ref = javaObjs.get(refnum);
if (ref == null) {
throw new RuntimeException("unknown java Ref: "+refnum);
}
return ref;
}
}
// GoRefQueue is a queue of GoRefs that are no longer live. An internal thread
// processes the queue and decrement the reference count on the Go side.
static class GoRefQueue extends ReferenceQueue<GoObject> {
// The set of tracked GoRefs. If we don't hold on to the GoRef instances, the Java GC
// will not add them to the queue when their referents are reclaimed.
private final Collection<GoRef> refs = Collections.synchronizedCollection(new HashSet<GoRef>());
void track(int refnum, GoObject obj) {
refs.add(new GoRef(refnum, obj, this));
}
GoRefQueue() {
Thread daemon = new Thread(new Runnable() {
@Override public void run() {
while (true) {
try {
GoRef ref = (GoRef)remove();
refs.remove(ref);
destroyRef(ref.refnum);
ref.clear();
} catch (InterruptedException e) {
// Ignore
}
}
}
});
daemon.setDaemon(true);
daemon.setName("GoRefQueue Finalizer Thread");
daemon.start();
}
}
// A GoRef is a PhantomReference to a Java proxy for a Go object.
// GoRefs are enqueued to the singleton GoRefQueue when no longer live,
// so the corresponding reference count can be decremented.
static class GoRef extends PhantomReference<GoObject> {
final int refnum;
GoRef(int refnum, GoObject obj, GoRefQueue q) {
super(obj, q);
if (refnum > 0) {
throw new RuntimeException("GoRef instantiated with a Java refnum " + refnum);
}
this.refnum = refnum;
}
}
// RefMap is a mapping of integers to Ref objects.
//
// The integers can be sparse. In Go this would be a map[int]*Ref.
static final class RefMap {
private int next = 0;
private int live = 0;
private int[] keys = new int[16];
private Ref[] objs = new Ref[16];
RefMap() {}
Ref get(int key) {
int i = Arrays.binarySearch(keys, 0, next, key);
if (i >= 0) {
return objs[i];
}
return null;
}
void remove(int key) {
int i = Arrays.binarySearch(keys, 0, next, key);
if (i >= 0) {
if (objs[i] != null) {
objs[i] = null;
live--;
}
}
}
void put(int key, Ref obj) {
if (obj == null) {
throw new RuntimeException("put a null ref (with key "+key+")");
}
int i = Arrays.binarySearch(keys, 0, next, key);
if (i >= 0) {
if (objs[i] == null) {
objs[i] = obj;
live++;
}
if (objs[i] != obj) {
throw new RuntimeException("replacing an existing ref (with key "+key+")");
}
return;
}
if (next >= keys.length) {
grow();
i = Arrays.binarySearch(keys, 0, next, key);
}
i = ~i;
if (i < next) {
// Insert, shift everything afterwards down.
System.arraycopy(keys, i, keys, i+1, next-i);
System.arraycopy(objs, i, objs, i+1, next-i);
}
keys[i] = key;
objs[i] = obj;
live++;
next++;
}
private void grow() {
// Compact and (if necessary) grow backing store.
int[] newKeys;
Ref[] newObjs;
int len = 2*roundPow2(live);
if (len > keys.length) {
newKeys = new int[keys.length*2];
newObjs = new Ref[objs.length*2];
} else {
newKeys = keys;
newObjs = objs;
}
int j = 0;
for (int i = 0; i < keys.length; i++) {
if (objs[i] != null) {
newKeys[j] = keys[i];
newObjs[j] = objs[i];
j++;
}
}
for (int i = j; i < newKeys.length; i++) {
newKeys[i] = 0;
newObjs[i] = null;
}
keys = newKeys;
objs = newObjs;
next = j;
if (live != next) {
throw new RuntimeException("bad state: live="+live+", next="+next);
}
}
private static int roundPow2(int x) {
int p = 1;
while (p < x) {
p *= 2;
}
return p;
}
}
}

162
bind/java/SeqBench.java Normal file
View file

@ -0,0 +1,162 @@
// 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 go;
import android.test.InstrumentationTestCase;
import android.util.Log;
import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import benchmark.*;
public class SeqBench extends InstrumentationTestCase {
public static class AnI implements I {
@Override public void f() {
}
}
private static class Benchmarks implements benchmark.Benchmarks {
private static Map<String, Runnable> benchmarks;
private static ExecutorService executor = Executors.newSingleThreadExecutor();
static {
benchmarks = new HashMap<String, Runnable>();
benchmarks.put("Empty", new Runnable() {
@Override public void run() {
}
});
benchmarks.put("Noargs", new Runnable() {
@Override public void run() {
Benchmark.noargs();
}
});
benchmarks.put("Onearg", new Runnable() {
@Override public void run() {
Benchmark.onearg(0);
}
});
benchmarks.put("Manyargs", new Runnable() {
@Override public void run() {
Benchmark.manyargs(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
}
});
benchmarks.put("Oneret", new Runnable() {
@Override public void run() {
Benchmark.oneret();
}
});
final I javaRef = new AnI();
benchmarks.put("Refforeign", new Runnable() {
@Override public void run() {
Benchmark.ref(javaRef);
}
});
final I goRef = Benchmark.newI();
benchmarks.put("Refgo", new Runnable() {
@Override public void run() {
Benchmark.ref(goRef);
}
});
benchmarks.put("StringShort", new Runnable() {
@Override public void run() {
Benchmark.string(Benchmark.ShortString);
}
});
benchmarks.put("StringLong", new Runnable() {
@Override public void run() {
Benchmark.string(Benchmark.LongString);
}
});
benchmarks.put("StringShortUnicode", new Runnable() {
@Override public void run() {
Benchmark.string(Benchmark.ShortStringUnicode);
}
});
benchmarks.put("StringLongUnicode", new Runnable() {
@Override public void run() {
Benchmark.string(Benchmark.LongStringUnicode);
}
});
benchmarks.put("StringRetShort", new Runnable() {
@Override public void run() {
Benchmark.stringRetShort();
}
});
benchmarks.put("StringRetLong", new Runnable() {
@Override public void run() {
Benchmark.stringRetLong();
}
});
final byte[] shortSlice = Benchmark.getShortSlice();
benchmarks.put("SliceShort", new Runnable() {
@Override public void run() {
Benchmark.slice(shortSlice);
}
});
final byte[] longSlice = Benchmark.getLongSlice();
benchmarks.put("SliceLong", new Runnable() {
@Override public void run() {
Benchmark.slice(longSlice);
}
});
}
public void runDirect(String name, final long n) {
final Runnable r = benchmarks.get(name);
try {
executor.submit(new Runnable() {
@Override public void run() {
for (int i = 0; i < n; i++) {
r.run();
}
}
}).get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void run(String name, long n) {
final Runnable r = benchmarks.get(name);
for (int i = 0; i < n; i++) {
r.run();
}
}
@Override public I newI() {
return new AnI();
}
@Override public void ref(I i) {
}
@Override public void noargs() {
}
@Override public void onearg(long i) {
}
@Override public long oneret() {
return 0;
}
@Override public void manyargs(long p0, long p1, long p2, long p3, long p4, long p5, long p6, long p7, long gp8, long p9) {
}
@Override public void string(String s) {
}
@Override public void slice(byte[] s) {
}
@Override public String stringRetShort() {
return Benchmark.ShortString;
}
@Override public String stringRetLong() {
return Benchmark.LongString;
}
}
public void testBenchmark() {
Benchmark.runBenchmarks(new Benchmarks());
}
}

602
bind/java/SeqTest.java Normal file
View file

@ -0,0 +1,602 @@
// Copyright 2014 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 go;
import android.test.InstrumentationTestCase;
import android.test.MoreAsserts;
import java.util.Arrays;
import java.util.Random;
import testpkg.*;
import secondpkg.Secondpkg;
public class SeqTest extends InstrumentationTestCase {
public SeqTest() {
}
public void testConst() {
assertEquals("const String", "a string", Testpkg.AString);
assertEquals("const Int", 7, Testpkg.AnInt);
assertEquals("const Bool", true, Testpkg.ABool);
assertEquals("const Float", 0.12345, Testpkg.AFloat, 0.0001);
assertEquals("const MinInt32", -1<<31, Testpkg.MinInt32);
assertEquals("const MaxInt32", (1<<31) - 1, Testpkg.MaxInt32);
assertEquals("const MinInt64", -1L<<63, Testpkg.MinInt64);
assertEquals("const MaxInt64", (1L<<63) - 1, Testpkg.MaxInt64);
assertEquals("const SmallestNonzeroFloat64", 4.940656458412465441765687928682213723651e-324, Testpkg.SmallestNonzeroFloat64, 1e-323);
assertEquals("const MaxFloat64", 1.797693134862315708145274237317043567981e+308, Testpkg.MaxFloat64, 0.0001);
assertEquals("const SmallestNonzeroFloat32", 1.401298464324817070923729583289916131280e-45, Testpkg.SmallestNonzeroFloat32, 1e-44);
assertEquals("const MaxFloat32", 3.40282346638528859811704183484516925440e+38, Testpkg.MaxFloat32, 0.0001);
assertEquals("const Log2E", 1/0.693147180559945309417232121458176568075500134360255254120680009, Testpkg.Log2E, 0.0001);
}
public void testRefMap() {
// Ensure that the RefMap.live count is kept in sync
// even a particular reference number is removed and
// added again
Seq.RefMap m = new Seq.RefMap();
Seq.Ref r = new Seq.Ref(1, null);
m.put(r.refnum, r);
m.remove(r.refnum);
m.put(r.refnum, r);
// Force the RefMap to grow, to activate the sanity
// checking of the live count in RefMap.grow.
for (int i = 2; i < 24; i++) {
m.put(i, new Seq.Ref(i, null));
}
}
public void testVar() {
assertEquals("var StringVar", "a string var", Testpkg.getStringVar());
String newStringVar = "a new string var";
Testpkg.setStringVar(newStringVar);
assertEquals("var StringVar", newStringVar, Testpkg.getStringVar());
assertEquals("var IntVar", 77, Testpkg.getIntVar());
long newIntVar = 777;
Testpkg.setIntVar(newIntVar);
assertEquals("var IntVar", newIntVar, Testpkg.getIntVar());
S s0 = Testpkg.getStructVar();
assertEquals("var StructVar", "a struct var", s0.string());
S s1 = Testpkg.new_();
Testpkg.setStructVar(s1);
assertEquals("var StructVar", s1.string(), Testpkg.getStructVar().string());
AnI obj = new AnI();
obj.name = "this is an I";
Testpkg.setInterfaceVar(obj);
assertEquals("var InterfaceVar", obj.string(), Testpkg.getInterfaceVar().string());
}
public void testAssets() {
// Make sure that a valid context is set before reading assets
Seq.setContext(getInstrumentation().getContext());
String want = "Hello, Assets.\n";
String got = Testpkg.readAsset();
assertEquals("Asset read", want, got);
}
public void testAdd() {
long res = Testpkg.add(3, 4);
assertEquals("Unexpected arithmetic failure", 7, res);
}
public void testBool() {
assertTrue(Testpkg.negate(false));
assertFalse(Testpkg.negate(true));
}
public void testShortString() {
String want = "a short string";
String got = Testpkg.strDup(want);
assertEquals("Strings should match", want, got);
want = "";
got = Testpkg.strDup(want);
assertEquals("Strings should match (empty string)", want, got);
got = Testpkg.strDup(null);
assertEquals("Strings should match (null string)", want, got);
}
public void testLongString() {
StringBuilder b = new StringBuilder();
for (int i = 0; i < 128*1024; i++) {
b.append("0123456789");
}
String want = b.toString();
String got = Testpkg.strDup(want);
assertEquals("Strings should match", want, got);
}
public void testUnicode() {
String[] tests = new String[]{
"abcxyz09{}",
"Hello, 世界",
"\uffff\uD800\uDC00\uD800\uDC01\uD808\uDF45\uDBFF\uDFFF",
// From Go std lib tests in unicode/utf16/utf16_test.go
"\u0001\u0002\u0003\u0004",
"\uffff\ud800\udc00\ud800\udc01\ud808\udf45\udbff\udfff",
"\ud800a",
"\udfff"
};
String[] wants = new String[]{
"abcxyz09{}",
"Hello, 世界",
"\uffff\uD800\uDC00\uD800\uDC01\uD808\uDF45\uDBFF\uDFFF",
"\u0001\u0002\u0003\u0004",
"\uffff\ud800\udc00\ud800\udc01\ud808\udf45\udbff\udfff",
"\ufffda",
"\ufffd"
};
for (int i = 0; i < tests.length; i++) {
String got = Testpkg.strDup(tests[i]);
String want = wants[i];
assertEquals("Strings should match", want, got);
}
}
public void testNilErr() throws Exception {
Testpkg.err(null); // returns nil, no exception
}
public void testErr() {
String msg = "Go errors are dropped into the confusing space of exceptions";
try {
Testpkg.err(msg);
fail("expected non-nil error to be turned into an exception");
} catch (Exception e) {
assertEquals("messages should match", msg, e.getMessage());
}
}
public void testByteArray() {
for (int i = 0; i < 2048; i++) {
if (i == 0) {
byte[] got = Testpkg.bytesAppend(null, null);
assertEquals("Bytes(null+null) should match", (byte[])null, got);
got = Testpkg.bytesAppend(new byte[0], new byte[0]);
assertEquals("Bytes(empty+empty) should match", (byte[])null, got);
continue;
}
byte[] want = new byte[i];
new Random().nextBytes(want);
byte[] s1 = null;
byte[] s2 = null;
if (i > 0) {
s1 = Arrays.copyOfRange(want, 0, 1);
}
if (i > 1) {
s2 = Arrays.copyOfRange(want, 1, i);
}
byte[] got = Testpkg.bytesAppend(s1, s2);
MoreAsserts.assertEquals("Bytes(len="+i+") should match", want, got);
}
}
// Test for golang.org/issue/9486.
public void testByteArrayAfterString() {
byte[] bytes = new byte[1024];
for (int i=0; i < bytes.length; i++) {
bytes[i] = 8;
}
String stuff = "stuff";
byte[] got = Testpkg.appendToString(stuff, bytes);
try {
byte[] s = stuff.getBytes("UTF-8");
byte[] want = new byte[s.length + bytes.length];
System.arraycopy(s, 0, want, 0, s.length);
System.arraycopy(bytes, 0, want, s.length, bytes.length);
MoreAsserts.assertEquals("Bytes should match", want, got);
} catch (Exception e) {
fail("Cannot perform the test: " + e.toString());
}
}
public void testGoRefGC() {
S s = Testpkg.new_();
runGC();
long collected = Testpkg.numSCollected();
assertEquals("Only S should be pinned", 0, collected);
s = null;
runGC();
collected = Testpkg.numSCollected();
assertEquals("S should be collected", 1, collected);
}
private class AnI implements I {
public void e() throws Exception {
throw new Exception("my exception from E");
}
boolean calledF;
public void f() {
calledF = true;
}
public I i() {
return this;
}
public S s() {
return Testpkg.new_();
}
public String stoString(S s) {
return s.string();
}
public long v() {
return 1234;
}
public long ve() throws Exception {
throw new Exception("my exception from VE");
}
public String name;
public String string() {
return name;
}
}
// TODO(hyangah): add tests for methods that take parameters.
public void testInterfaceMethodReturnsError() {
final AnI obj = new AnI();
try {
Testpkg.callE(obj);
fail("Expecting exception but none was thrown.");
} catch (Exception e) {
assertEquals("Error messages should match", "my exception from E", e.getMessage());
}
}
public void testInterfaceMethodVoid() {
final AnI obj = new AnI();
Testpkg.callF(obj);
assertTrue("Want AnI.F to be called", obj.calledF);
}
public void testInterfaceMethodReturnsInterface() {
AnI obj = new AnI();
obj.name = "testing AnI.I";
I i = Testpkg.callI(obj);
assertEquals("Want AnI.I to return itself", i.string(), obj.string());
runGC();
i = Testpkg.callI(obj);
assertEquals("Want AnI.I to return itself", i.string(), obj.string());
}
public void testInterfaceMethodReturnsStructPointer() {
final AnI obj = new AnI();
for (int i = 0; i < 5; i++) {
S s = Testpkg.callS(obj);
runGC();
}
}
public void testInterfaceMethodTakesStructPointer() {
final AnI obj = new AnI();
S s = Testpkg.callS(obj);
String got = obj.stoString(s);
String want = s.string();
assertEquals("Want AnI.StoString(s) to call s's String", want, got);
}
public void testInterfaceMethodReturnsInt() {
final AnI obj = new AnI();
assertEquals("Values must match", 1234, Testpkg.callV(obj));
}
public void testInterfaceMethodReturnsIntOrError() {
final AnI obj = new AnI();
try {
long v = Testpkg.callVE(obj);
fail("Expecting exception but none was thrown and got value " + v);
} catch (Exception e) {
assertEquals("Error messages should match", "my exception from VE", e.getMessage());
}
}
boolean finalizedAnI;
private class AnI_Traced extends AnI {
@Override
public void finalize() throws Throwable {
finalizedAnI = true;
super.finalize();
}
}
public void testJavaRefKeep() {
finalizedAnI = false;
AnI obj = new AnI_Traced();
Testpkg.callF(obj);
assertTrue("want F to be called", obj.calledF);
Testpkg.callF(obj);
obj = null;
int attempts = 0;
while (true) {
runGC();
if (finalizedAnI)
break;
attempts++;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (attempts >= 10)
fail("want obj not to be kept by Go; tried " + attempts + " garbage collections.");
}
finalizedAnI = false;
obj = new AnI_Traced();
Testpkg.keep(obj);
obj = null;
runGC();
assertFalse("want obj to be kept live by Go", finalizedAnI);
}
private int countI = 0;
private class CountI implements I {
public void f() { countI++; }
public void e() throws Exception {}
public I i() { return null; }
public S s() { return null; }
public String stoString(S s) { return ""; }
public long v() { return 0; }
public long ve() throws Exception { return 0; }
public String string() { return ""; }
}
public void testGoRefMapGrow() {
CountI obj = new CountI();
Testpkg.keep(obj);
// Push active references beyond base map size.
for (int i = 0; i < 24; i++) {
CountI o = new CountI();
Testpkg.callF(o);
if (i%3==0) {
Testpkg.keep(o);
}
}
runGC();
for (int i = 0; i < 128; i++) {
Testpkg.callF(new CountI());
}
Testpkg.callF(obj); // original object needs to work.
assertEquals(countI, 1+24+128);
}
private void runGC() {
System.gc();
System.runFinalization();
Testpkg.gc();
System.gc();
System.runFinalization();
}
public void testUnnamedParams() {
final String msg = "1234567";
assertEquals("want the length of \"1234567\" passed after unnamed params",
7, Testpkg.unnamedParams(10, 20, msg));
}
public void testPointerToStructAsField() {
Node a = Testpkg.newNode("A");
Node b = Testpkg.newNode("B");
a.setNext(b);
String got = a.string();
assertEquals("want Node A points to Node B", "A:B:<end>", got);
}
public void testImplementsInterface() {
Interface intf = Testpkg.newConcrete();
}
public void testErrorField() {
Node n = Testpkg.newNode("ErrTest");
Exception want = new Exception("an error message");
n.setErr(want);
Exception got = n.getErr();
assertTrue("want back the error we set", want == got);
String msg = Testpkg.errorMessage(want);
assertEquals("the error message must match", want.getMessage(), msg);
}
public void testErrorDup() {
Exception err = Testpkg.getGlobalErr();
assertTrue("the Go error instance must preserve its identity", Testpkg.isGlobalErr(err));
assertEquals("the Go error message must be preserved", "global err", err.getMessage());
}
//test if we have JNI local reference table overflow error
public void testLocalReferenceOverflow() {
Testpkg.callWithCallback(new GoCallback() {
@Override
public void varUpdate() {
//do nothing
}
});
}
public void testNullReferences() {
assertTrue(Testpkg.callWithNull(null, new NullTest() {
public NullTest null_() {
return null;
}
}));
assertEquals("Go nil interface is null", null, Testpkg.newNullInterface());
assertEquals("Go nil struct pointer is null", null, Testpkg.newNullStruct());
Issue20330 nullArger = new Issue20330();
assertTrue(nullArger.callWithNull(null));
}
public void testPassByteArray() {
Testpkg.passByteArray(new B() {
@Override public void b(byte[] b) {
byte[] want = new byte[]{1, 2, 3, 4};
MoreAsserts.assertEquals("bytes should match", want, b);
}
});
}
public void testReader() {
byte[] b = new byte[8];
try {
long n = Testpkg.readIntoByteArray(b);
assertEquals("wrote to the entire byte array", b.length, n);
byte[] want = new byte[b.length];
for (int i = 0; i < want.length; i++)
want[i] = (byte)i;
MoreAsserts.assertEquals("bytes should match", want, b);
} catch (Exception e) {
fail("Failed to write: " + e.toString());
}
}
public void testGoroutineCallback() {
Testpkg.goroutineCallback(new Receiver() {
@Override public void hello(String msg) {
}
});
}
public void testImportedPkg() {
Testpkg.callImportedI(new secondpkg.I() {
@Override public long f(long i) {
return i;
}
});
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);
ImportedFields fields = Testpkg.newImportedFields();
i = fields.getI();
s = fields.getS();
fields.setI(i);
fields.setS(s);
Testpkg.withImportedI(i);
Testpkg.withImportedS(s);
secondpkg.IF f = new AnI();
f = Testpkg.new_();
secondpkg.Ser ser = Testpkg.newSer();
}
public void testRoundtripEquality() {
I want = new AnI();
assertTrue("java object passed through Go should not be wrapped", want == Testpkg.iDup(want));
InterfaceDupper idup = new InterfaceDupper(){
@Override public Interface iDup(Interface i) {
return i;
}
};
assertTrue("Go interface passed through Java should not be wrapped", Testpkg.callIDupper(idup));
ConcreteDupper cdup = new ConcreteDupper(){
@Override public Concrete cDup(Concrete c) {
return c;
}
};
assertTrue("Go struct passed through Java should not be wrapped", Testpkg.callCDupper(cdup));
}
public void testConstructor() {
Interface i = new Concrete();
i.f();
S2 s = new S2(1, 2);
assertEquals("new S2().sum", 3.0, s.sum());
assertEquals("new S2().tryTwoStrings", "gostring", s.tryTwoStrings("go", "string"));
new S3();
S4 s4 = new S4(123);
assertEquals("Constructor argument", 123, s4.getI());
s4 = new S4(123.456);
assertEquals("Overloaded constructor argument", 123, s4.getI());
s4 = new S4(false);
assertEquals("Exceptional constructor", 0, s4.getI());
try {
s4 = new S4(true);
fail("Constructor error wasn't caught");
} catch (Exception e) {
}
}
public void testEmptyError() {
try {
Testpkg.emptyError();
fail("Empty error wasn't caught");
} catch (Exception e) {
}
EmptyErrorer empty = new EmptyErrorer() {
@Override public void emptyError() throws Exception {
throw new Exception("");
}
};
try {
Testpkg.callEmptyError(empty);
fail("Empty exception wasn't caught");
} catch (Exception e) {
}
}
public void testInitCaller() {
Testpkg.init();
InitCaller initer = Testpkg.newInitCaller();
initer.init();
}
public void testSIGPIPE() {
Testpkg.testSIGPIPE();
}
public void testTags() {
assertEquals("Constant from a tagged file", 42, Testpkg.TaggedConst);
}
public void testClassNameWithPackageName() {
testpkg.Testpkg_ o = new secondpkg.Secondpkg_();
secondpkg.Secondpkg_ o2 = Secondpkg.newSecondpkg();
o2.m();
o2.setV("hi");
assertEquals(o2.getV(), "hi");
Testpkg.clashingParameterFromOtherPackage(o2);
}
}

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.
#include <jni.h>
#include "seq_android.h"
#include "_cgo_export.h"
JNIEXPORT void JNICALL
Java_go_Seq_setContext(JNIEnv* env, jclass clazz, jobject ctx) {
JavaVM* vm;
if ((*env)->GetJavaVM(env, &vm) != 0) {
LOG_FATAL("failed to get JavaVM");
}
setContext(vm, (*env)->NewGlobalRef(env, ctx));
}

View file

@ -0,0 +1,21 @@
// 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 java
// #cgo LDFLAGS: -llog
//
//#include <jni.h>
import "C"
import (
"unsafe"
"golang.org/x/mobile/internal/mobileinit"
)
//export setContext
func setContext(vm *C.JavaVM, ctx C.jobject) {
mobileinit.SetCurrentContext(unsafe.Pointer(vm), uintptr(ctx))
}

8
bind/java/doc.go Normal file
View file

@ -0,0 +1,8 @@
// Copyright 2015 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 java implements the Java language bindings.
//
// See the design document (http://golang.org/s/gobind).
package java

View file

@ -0,0 +1,401 @@
// 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.
// C support functions for bindings. This file is copied into the
// generated gomobile_bind package and compiled along with the
// generated binding files.
#include <android/log.h>
#include <errno.h>
#include <jni.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "seq.h"
#include "_cgo_export.h"
#define NULL_REFNUM 41
// initClasses are only exported from Go if reverse bindings are used.
// If they're not, weakly define a no-op function.
__attribute__((weak)) void initClasses(void) { }
static JavaVM *jvm;
// jnienvs holds the per-thread JNIEnv* for Go threads where we called AttachCurrentThread.
// A pthread key destructor is supplied to call DetachCurrentThread on exit. This trick is
// documented in http://developer.android.com/training/articles/perf-jni.html under "Threads".
static pthread_key_t jnienvs;
static jclass seq_class;
static jmethodID seq_getRef;
static jmethodID seq_decRef;
static jmethodID seq_incRef;
static jmethodID seq_incGoObjectRef;
static jmethodID seq_incRefnum;
static jfieldID ref_objField;
static jclass throwable_class;
// env_destructor is registered as a thread data key destructor to
// clean up a Go thread that is attached to the JVM.
static void env_destructor(void *env) {
if ((*jvm)->DetachCurrentThread(jvm) != JNI_OK) {
LOG_INFO("failed to detach current thread");
}
}
static JNIEnv *go_seq_get_thread_env(void) {
JNIEnv *env;
jint ret = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_6);
if (ret != JNI_OK) {
if (ret != JNI_EDETACHED) {
LOG_FATAL("failed to get thread env");
}
if ((*jvm)->AttachCurrentThread(jvm, &env, NULL) != JNI_OK) {
LOG_FATAL("failed to attach current thread");
}
pthread_setspecific(jnienvs, env);
}
return env;
}
void go_seq_maybe_throw_exception(JNIEnv *env, jobject exc) {
if (exc != NULL) {
(*env)->Throw(env, exc);
}
}
jobject go_seq_get_exception(JNIEnv *env) {
jthrowable exc = (*env)->ExceptionOccurred(env);
if (!exc) {
return NULL;
}
(*env)->ExceptionClear(env);
return exc;
}
jbyteArray go_seq_to_java_bytearray(JNIEnv *env, nbyteslice s, int copy) {
if (s.ptr == NULL) {
return NULL;
}
jbyteArray res = (*env)->NewByteArray(env, s.len);
if (res == NULL) {
LOG_FATAL("NewByteArray failed");
}
(*env)->SetByteArrayRegion(env, res, 0, s.len, s.ptr);
if (copy) {
free(s.ptr);
}
return res;
}
#define surr1 0xd800
#define surr2 0xdc00
#define surr3 0xe000
// Unicode replacement character
#define replacementChar 0xFFFD
#define rune1Max ((1<<7) - 1)
#define rune2Max ((1<<11) - 1)
#define rune3Max ((1<<16) - 1)
// Maximum valid Unicode code point.
#define MaxRune 0x0010FFFF
#define surrogateMin 0xD800
#define surrogateMax 0xDFFF
// 0011 1111
#define maskx 0x3F
// 1000 0000
#define tx 0x80
// 1100 0000
#define t2 0xC0
// 1110 0000
#define t3 0xE0
// 1111 0000
#define t4 0xF0
// encode_rune writes into p (which must be large enough) the UTF-8 encoding
// of the rune. It returns the number of bytes written.
static int encode_rune(uint8_t *p, uint32_t r) {
if (r <= rune1Max) {
p[0] = (uint8_t)r;
return 1;
} else if (r <= rune2Max) {
p[0] = t2 | (uint8_t)(r>>6);
p[1] = tx | (((uint8_t)(r))&maskx);
return 2;
} else {
if (r > MaxRune || (surrogateMin <= r && r <= surrogateMax)) {
r = replacementChar;
}
if (r <= rune3Max) {
p[0] = t3 | (uint8_t)(r>>12);
p[1] = tx | (((uint8_t)(r>>6))&maskx);
p[2] = tx | (((uint8_t)(r))&maskx);
return 3;
} else {
p[0] = t4 | (uint8_t)(r>>18);
p[1] = tx | (((uint8_t)(r>>12))&maskx);
p[2] = tx | (((uint8_t)(r>>6))&maskx);
p[3] = tx | (((uint8_t)(r))&maskx);
return 4;
}
}
}
// utf16_decode decodes an array of UTF16 characters to a UTF-8 encoded
// nstring copy. The support functions and utf16_decode itself are heavily
// based on the unicode/utf8 and unicode/utf16 Go packages.
static nstring utf16_decode(jchar *chars, jsize len) {
jsize worstCaseLen = 4*len;
uint8_t *buf = malloc(worstCaseLen);
if (buf == NULL) {
LOG_FATAL("utf16Decode: malloc failed");
}
jsize nsrc = 0;
jsize ndst = 0;
while (nsrc < len) {
uint32_t r = chars[nsrc];
nsrc++;
if (surr1 <= r && r < surr2 && nsrc < len) {
uint32_t r2 = chars[nsrc];
if (surr2 <= r2 && r2 < surr3) {
nsrc++;
r = (((r-surr1)<<10) | (r2 - surr2)) + 0x10000;
}
}
if (ndst + 4 > worstCaseLen) {
LOG_FATAL("utf16Decode: buffer overflow");
}
ndst += encode_rune(buf + ndst, r);
}
struct nstring res = {.chars = buf, .len = ndst};
return res;
}
nstring go_seq_from_java_string(JNIEnv *env, jstring str) {
struct nstring res = {NULL, 0};
if (str == NULL) {
return res;
}
jsize nchars = (*env)->GetStringLength(env, str);
if (nchars == 0) {
return res;
}
jchar *chars = (jchar *)(*env)->GetStringChars(env, str, NULL);
if (chars == NULL) {
LOG_FATAL("GetStringChars failed");
}
nstring nstr = utf16_decode(chars, nchars);
(*env)->ReleaseStringChars(env, str, chars);
return nstr;
}
nbyteslice go_seq_from_java_bytearray(JNIEnv *env, jbyteArray arr, int copy) {
struct nbyteslice res = {NULL, 0};
if (arr == NULL) {
return res;
}
jsize len = (*env)->GetArrayLength(env, arr);
if (len == 0) {
return res;
}
jbyte *ptr = (*env)->GetByteArrayElements(env, arr, NULL);
if (ptr == NULL) {
LOG_FATAL("GetByteArrayElements failed");
}
if (copy) {
void *ptr_copy = (void *)malloc(len);
if (ptr_copy == NULL) {
LOG_FATAL("malloc failed");
}
memcpy(ptr_copy, ptr, len);
(*env)->ReleaseByteArrayElements(env, arr, ptr, JNI_ABORT);
ptr = (jbyte *)ptr_copy;
}
res.ptr = ptr;
res.len = len;
return res;
}
int32_t go_seq_to_refnum_go(JNIEnv *env, jobject o) {
if (o == NULL) {
return NULL_REFNUM;
}
return (int32_t)(*env)->CallStaticIntMethod(env, seq_class, seq_incGoObjectRef, o);
}
int32_t go_seq_to_refnum(JNIEnv *env, jobject o) {
if (o == NULL) {
return NULL_REFNUM;
}
return (int32_t)(*env)->CallStaticIntMethod(env, seq_class, seq_incRef, o);
}
int32_t go_seq_unwrap(jint refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject jobj = go_seq_from_refnum(env, refnum, NULL, NULL);
int32_t goref = go_seq_to_refnum_go(env, jobj);
go_seq_pop_local_frame(env);
return goref;
}
jobject go_seq_from_refnum(JNIEnv *env, int32_t refnum, jclass proxy_class, jmethodID proxy_cons) {
if (refnum == NULL_REFNUM) {
return NULL;
}
if (refnum < 0) { // Go object
// return new <Proxy>(refnum)
return (*env)->NewObject(env, proxy_class, proxy_cons, refnum);
}
// Seq.Ref ref = Seq.getRef(refnum)
jobject ref = (*env)->CallStaticObjectMethod(env, seq_class, seq_getRef, (jint)refnum);
if (ref == NULL) {
LOG_FATAL("Unknown reference: %d", refnum);
}
// Go incremented the reference count just before passing the refnum. Decrement it here.
(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)refnum);
// return ref.obj
return (*env)->GetObjectField(env, ref, ref_objField);
}
// go_seq_to_java_string converts a nstring to a jstring.
jstring go_seq_to_java_string(JNIEnv *env, nstring str) {
jstring s = (*env)->NewString(env, str.chars, str.len/2);
if (str.chars != NULL) {
free(str.chars);
}
return s;
}
// go_seq_push_local_frame retrieves or creates the JNIEnv* for the current thread
// and pushes a JNI reference frame. Must be matched with call to go_seq_pop_local_frame.
JNIEnv *go_seq_push_local_frame(jint nargs) {
JNIEnv *env = go_seq_get_thread_env();
// Given the number of function arguments, compute a conservative bound for the minimal frame size.
// Assume two slots for each per parameter (Seq.Ref and Seq.Object) and add extra
// extra space for the receiver, the return value, and exception (if any).
jint frameSize = 2*nargs + 10;
if ((*env)->PushLocalFrame(env, frameSize) < 0) {
LOG_FATAL("PushLocalFrame failed");
}
return env;
}
// Pop the current local frame, freeing all JNI local references in it
void go_seq_pop_local_frame(JNIEnv *env) {
(*env)->PopLocalFrame(env, NULL);
}
void go_seq_inc_ref(int32_t ref) {
JNIEnv *env = go_seq_get_thread_env();
(*env)->CallStaticVoidMethod(env, seq_class, seq_incRefnum, (jint)ref);
}
void go_seq_dec_ref(int32_t ref) {
JNIEnv *env = go_seq_get_thread_env();
(*env)->CallStaticVoidMethod(env, seq_class, seq_decRef, (jint)ref);
}
JNIEXPORT void JNICALL
Java_go_Seq_init(JNIEnv *env, jclass clazz) {
if ((*env)->GetJavaVM(env, &jvm) != 0) {
LOG_FATAL("failed to get JVM");
}
if (pthread_key_create(&jnienvs, env_destructor) != 0) {
LOG_FATAL("failed to initialize jnienvs thread local storage");
}
seq_class = (*env)->NewGlobalRef(env, clazz);
seq_getRef = (*env)->GetStaticMethodID(env, seq_class, "getRef", "(I)Lgo/Seq$Ref;");
if (seq_getRef == NULL) {
LOG_FATAL("failed to find method Seq.getRef");
}
seq_decRef = (*env)->GetStaticMethodID(env, seq_class, "decRef", "(I)V");
if (seq_decRef == NULL) {
LOG_FATAL("failed to find method Seq.decRef");
}
seq_incRefnum = (*env)->GetStaticMethodID(env, seq_class, "incRefnum", "(I)V");
if (seq_incRefnum == NULL) {
LOG_FATAL("failed to find method Seq.incRefnum");
}
seq_incRef = (*env)->GetStaticMethodID(env, seq_class, "incRef", "(Ljava/lang/Object;)I");
if (seq_incRef == NULL) {
LOG_FATAL("failed to find method Seq.incRef");
}
seq_incGoObjectRef = (*env)->GetStaticMethodID(env, seq_class, "incGoObjectRef", "(Lgo/Seq$GoObject;)I");
if (seq_incGoObjectRef == NULL) {
LOG_FATAL("failed to find method Seq.incGoObjectRef");
}
jclass ref_class = (*env)->FindClass(env, "go/Seq$Ref");
if (ref_class == NULL) {
LOG_FATAL("failed to find the Seq.Ref class");
}
ref_objField = (*env)->GetFieldID(env, ref_class, "obj", "Ljava/lang/Object;");
if (ref_objField == NULL) {
LOG_FATAL("failed to find the Seq.Ref.obj field");
}
initClasses();
}
JNIEXPORT void JNICALL
Java_go_Seq_destroyRef(JNIEnv *env, jclass clazz, jint refnum) {
DestroyRef(refnum);
}
JNIEXPORT void JNICALL
Java_go_Seq_incGoRef(JNIEnv *env, jclass clazz, jint refnum, jobject ref) {
IncGoRef(refnum);
}
jclass go_seq_find_class(const char *name) {
JNIEnv *env = go_seq_push_local_frame(0);
jclass clazz = (*env)->FindClass(env, name);
if (clazz == NULL) {
(*env)->ExceptionClear(env);
} else {
clazz = (*env)->NewGlobalRef(env, clazz);
}
go_seq_pop_local_frame(env);
return clazz;
}
jmethodID go_seq_get_static_method_id(jclass clazz, const char *name, const char *sig) {
JNIEnv *env = go_seq_push_local_frame(0);
jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig);
if (m == NULL) {
(*env)->ExceptionClear(env);
}
go_seq_pop_local_frame(env);
return m;
}
jmethodID go_seq_get_method_id(jclass clazz, const char *name, const char *sig) {
JNIEnv *env = go_seq_push_local_frame(0);
jmethodID m = (*env)->GetMethodID(env, clazz, name, sig);
if (m == NULL) {
(*env)->ExceptionClear(env);
}
go_seq_pop_local_frame(env);
return m;
}
void go_seq_release_byte_array(JNIEnv *env, jbyteArray arr, jbyte* ptr) {
if (ptr != NULL) {
(*env)->ReleaseByteArrayElements(env, arr, ptr, 0);
}
}
int go_seq_isinstanceof(jint refnum, jclass clazz) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject obj = go_seq_from_refnum(env, refnum, NULL, NULL);
jboolean isinst = (*env)->IsInstanceOf(env, obj, clazz);
go_seq_pop_local_frame(env);
return isinst;
}

View file

@ -0,0 +1,98 @@
// 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 main
// Go support functions for bindings. This file is copied into the
// generated main package and compiled along with the generated binding
// files.
//#cgo CFLAGS: -Werror
//#cgo LDFLAGS: -llog
//#include <jni.h>
//#include <stdint.h>
//#include <stdlib.h>
//#include "seq_android.h"
import "C"
import (
"unsafe"
"golang.org/x/mobile/bind/seq"
)
// DestroyRef is called by Java to inform Go it is done with a reference.
//export DestroyRef
func DestroyRef(refnum C.int32_t) {
seq.Delete(int32(refnum))
}
// encodeString returns a copy of a Go string as a UTF16 encoded nstring.
// The returned data is freed in go_seq_to_java_string.
//
// encodeString uses UTF16 as the intermediate format. Note that UTF8 is an obvious
// alternative, but JNI only supports a C-safe variant of UTF8 (modified UTF8).
func encodeString(s string) C.nstring {
n := C.int(len(s))
if n == 0 {
return C.nstring{}
}
// Allocate enough for the worst case estimate, every character is a surrogate pair
worstCaseLen := 4 * len(s)
utf16buf := C.malloc(C.size_t(worstCaseLen))
if utf16buf == nil {
panic("encodeString: malloc failed")
}
chars := (*[1<<30 - 1]uint16)(unsafe.Pointer(utf16buf))[:worstCaseLen/2 : worstCaseLen/2]
nchars := seq.UTF16Encode(s, chars)
return C.nstring{chars: unsafe.Pointer(utf16buf), len: C.jsize(nchars*2)}
}
// decodeString decodes a UTF8 encoded nstring to a Go string. The data
// in str is freed after use.
func decodeString(str C.nstring) string {
if str.chars == nil {
return ""
}
chars := (*[1<<31 - 1]byte)(str.chars)[:str.len]
s := string(chars)
C.free(str.chars)
return s
}
// fromSlice converts a slice to a jbyteArray cast as a nbyteslice. If cpy
// is set, the returned slice is a copy to be free by go_seq_to_java_bytearray.
func fromSlice(s []byte, cpy bool) C.nbyteslice {
if s == nil || len(s) == 0 {
return C.nbyteslice{}
}
var ptr *C.jbyte
n := C.jsize(len(s))
if cpy {
ptr = (*C.jbyte)(C.malloc(C.size_t(n)))
if ptr == nil {
panic("fromSlice: malloc failed")
}
copy((*[1<<31 - 1]byte)(unsafe.Pointer(ptr))[:n], s)
} else {
ptr = (*C.jbyte)(unsafe.Pointer(&s[0]))
}
return C.nbyteslice{ptr: unsafe.Pointer(ptr), len: n}
}
// toSlice takes a nbyteslice (jbyteArray) and returns a byte slice
// with the data. If cpy is set, the slice contains a copy of the data and is
// freed.
func toSlice(s C.nbyteslice, cpy bool) []byte {
if s.ptr == nil || s.len == 0 {
return nil
}
var b []byte
if cpy {
b = C.GoBytes(s.ptr, C.int(s.len))
C.free(s.ptr)
} else {
b = (*[1<<31 - 1]byte)(unsafe.Pointer(s.ptr))[:s.len:s.len]
}
return b
}

67
bind/java/seq_android.h Normal file
View file

@ -0,0 +1,67 @@
// 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.
#ifndef __GO_SEQ_ANDROID_HDR__
#define __GO_SEQ_ANDROID_HDR__
#include <stdint.h>
#include <android/log.h>
// For abort()
#include <stdlib.h>
#include <jni.h>
#define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "go/Seq", __VA_ARGS__)
#define LOG_FATAL(...) \
{ \
__android_log_print(ANDROID_LOG_FATAL, "go/Seq", __VA_ARGS__); \
abort(); \
}
// Platform specific types
typedef struct nstring {
// UTF16 or UTF8 Encoded string. When converting from Java string to Go
// string, UTF16. When converting from Go to Java, UTF8.
void *chars;
// length in bytes, regardless of encoding
jsize len;
} nstring;
typedef struct nbyteslice {
void *ptr;
jsize len;
} nbyteslice;
typedef jlong nint;
extern void go_seq_dec_ref(int32_t ref);
extern void go_seq_inc_ref(int32_t ref);
// go_seq_unwrap takes a reference number to a Java wrapper and returns
// a reference number to its wrapped Go object.
extern int32_t go_seq_unwrap(jint refnum);
extern int32_t go_seq_to_refnum(JNIEnv *env, jobject o);
extern int32_t go_seq_to_refnum_go(JNIEnv *env, jobject o);
extern jobject go_seq_from_refnum(JNIEnv *env, int32_t refnum, jclass proxy_class, jmethodID proxy_cons);
extern void go_seq_maybe_throw_exception(JNIEnv *env, jobject msg);
// go_seq_get_exception returns any pending exception and clears the exception status.
extern jobject go_seq_get_exception(JNIEnv *env);
extern jbyteArray go_seq_to_java_bytearray(JNIEnv *env, nbyteslice s, int copy);
extern nbyteslice go_seq_from_java_bytearray(JNIEnv *env, jbyteArray s, int copy);
extern void go_seq_release_byte_array(JNIEnv *env, jbyteArray arr, jbyte* ptr);
extern jstring go_seq_to_java_string(JNIEnv *env, nstring str);
extern nstring go_seq_from_java_string(JNIEnv *env, jstring s);
// push_local_frame retrieves or creates the JNIEnv* for the current thread
// and pushes a JNI reference frame. Must be matched with call to pop_local_frame.
extern JNIEnv *go_seq_push_local_frame(jint cap);
// Pop the current local frame, releasing all JNI local references in it
extern void go_seq_pop_local_frame(JNIEnv *env);
// Return a global reference to the given class. Return NULL and clear exception if not found.
extern jclass go_seq_find_class(const char *name);
extern jmethodID go_seq_get_static_method_id(jclass clazz, const char *name, const char *sig);
extern jmethodID go_seq_get_method_id(jclass clazz, const char *name, const char *sig);
extern int go_seq_isinstanceof(jint refnum, jclass clazz);
#endif // __GO_SEQ_ANDROID_HDR__

256
bind/java/seq_test.go Normal file
View file

@ -0,0 +1,256 @@
// Copyright 2015 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 java
import (
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"testing"
"golang.org/x/mobile/internal/importers/java"
"golang.org/x/mobile/internal/sdkpath"
)
var gomobileBin string
func TestMain(m *testing.M) {
os.Exit(testMain(m))
}
func testMain(m *testing.M) int {
// Build gomobile and gobind and put them into PATH.
binDir, err := os.MkdirTemp("", "bind-java-test-")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(binDir)
exe := ""
if runtime.GOOS == "windows" {
exe = ".exe"
}
if runtime.GOOS != "android" {
gocmd := filepath.Join(runtime.GOROOT(), "bin", "go")
gomobileBin = filepath.Join(binDir, "gomobile"+exe)
gobindBin := filepath.Join(binDir, "gobind"+exe)
if out, err := exec.Command(gocmd, "build", "-o", gomobileBin, "golang.org/x/mobile/cmd/gomobile").CombinedOutput(); err != nil {
log.Fatalf("gomobile build failed: %v: %s", err, out)
}
if out, err := exec.Command(gocmd, "build", "-o", gobindBin, "golang.org/x/mobile/cmd/gobind").CombinedOutput(); err != nil {
log.Fatalf("gobind build failed: %v: %s", err, out)
}
path := binDir
if oldPath := os.Getenv("PATH"); oldPath != "" {
path += string(filepath.ListSeparator) + oldPath
}
os.Setenv("PATH", path)
}
return m.Run()
}
func TestClasses(t *testing.T) {
if !java.IsAvailable() {
t.Skipf("java importer is not available")
}
runTest(t, []string{
"golang.org/x/mobile/bind/testdata/testpkg/javapkg",
}, "", "ClassesTest")
}
func TestCustomPkg(t *testing.T) {
runTest(t, []string{
"golang.org/x/mobile/bind/testdata/testpkg",
}, "org.golang.custompkg", "CustomPkgTest")
}
func TestJavaSeqTest(t *testing.T) {
runTest(t, []string{
"golang.org/x/mobile/bind/testdata/testpkg",
"golang.org/x/mobile/bind/testdata/testpkg/secondpkg",
"golang.org/x/mobile/bind/testdata/testpkg/simplepkg",
}, "", "SeqTest")
}
// TestJavaSeqBench runs java test SeqBench.java, with the same
// environment requirements as TestJavaSeqTest.
//
// The benchmarks runs on the phone, so the benchmarkpkg implements
// rudimentary timing logic and outputs benchcmp compatible runtimes
// to logcat. Use
//
// adb logcat -v raw GoLog:* *:S
//
// while running the benchmark to see the results.
func TestJavaSeqBench(t *testing.T) {
if testing.Short() {
t.Skip("skipping benchmark in short mode.")
}
runTest(t, []string{"golang.org/x/mobile/bind/testdata/benchmark"}, "", "SeqBench")
}
// runTest runs the Android java test class specified with javaCls. If javaPkg is
// set, it is passed with the -javapkg flag to gomobile. The pkgNames lists the Go
// packages to bind for the test.
// This requires the gradle command to be in PATH and the Android SDK to be
// installed.
func runTest(t *testing.T, pkgNames []string, javaPkg, javaCls string) {
if gomobileBin == "" {
t.Skipf("no gomobile on %s", runtime.GOOS)
}
gradle, err := exec.LookPath("gradle")
if err != nil {
t.Skip("command gradle not found, skipping")
}
if _, err := sdkpath.AndroidHome(); err != nil {
t.Skip("Android SDK not found, skipping")
}
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("failed pwd: %v", err)
}
tmpdir, err := os.MkdirTemp("", "bind-java-seq-test-")
if err != nil {
t.Fatalf("failed to prepare temp dir: %v", err)
}
defer os.RemoveAll(tmpdir)
t.Logf("tmpdir = %s", tmpdir)
if err := os.Chdir(tmpdir); err != nil {
t.Fatalf("failed chdir: %v", err)
}
defer os.Chdir(cwd)
for _, d := range []string{"src/main", "src/androidTest/java/go", "libs", "src/main/res/values"} {
err = os.MkdirAll(filepath.Join(tmpdir, d), 0700)
if err != nil {
t.Fatal(err)
}
}
args := []string{"bind", "-tags", "aaa bbb", "-o", "pkg.aar"}
if javaPkg != "" {
args = append(args, "-javapkg", javaPkg)
}
args = append(args, pkgNames...)
cmd := exec.Command(gomobileBin, args...)
// Reverse binding doesn't work with Go module since imports starting with Java or ObjC are not valid FQDNs.
// Disable Go module explicitly until this problem is solved. See golang/go#27234.
cmd.Env = append(os.Environ(), "GO111MODULE=off")
buf, err := cmd.CombinedOutput()
if err != nil {
t.Logf("%s", buf)
t.Fatalf("failed to run gomobile bind: %v", err)
}
fname := filepath.Join(tmpdir, "libs", "pkg.aar")
err = cp(fname, filepath.Join(tmpdir, "pkg.aar"))
if err != nil {
t.Fatalf("failed to copy pkg.aar: %v", err)
}
fname = filepath.Join(tmpdir, "src/androidTest/java/go/"+javaCls+".java")
err = cp(fname, filepath.Join(cwd, javaCls+".java"))
if err != nil {
t.Fatalf("failed to copy SeqTest.java: %v", err)
}
fname = filepath.Join(tmpdir, "src/main/AndroidManifest.xml")
err = os.WriteFile(fname, []byte(androidmanifest), 0700)
if err != nil {
t.Fatalf("failed to write android manifest file: %v", err)
}
// Add a dummy string resource to avoid errors from the Android build system.
fname = filepath.Join(tmpdir, "src/main/res/values/strings.xml")
err = os.WriteFile(fname, []byte(stringsxml), 0700)
if err != nil {
t.Fatalf("failed to write strings.xml file: %v", err)
}
fname = filepath.Join(tmpdir, "build.gradle")
err = os.WriteFile(fname, []byte(buildgradle), 0700)
if err != nil {
t.Fatalf("failed to write build.gradle file: %v", err)
}
if buf, err := run(gradle + " connectedAndroidTest"); err != nil {
t.Logf("%s", buf)
t.Errorf("failed to run gradle test: %v", err)
}
}
func run(cmd string) ([]byte, error) {
c := strings.Split(cmd, " ")
return exec.Command(c[0], c[1:]...).CombinedOutput()
}
func cp(dst, src string) error {
r, err := os.Open(src)
if err != nil {
return fmt.Errorf("failed to read source: %v", err)
}
defer r.Close()
w, err := os.Create(dst)
if err != nil {
return fmt.Errorf("failed to open destination: %v", err)
}
_, err = io.Copy(w, r)
cerr := w.Close()
if err != nil {
return err
}
return cerr
}
const androidmanifest = `<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.BindTest"
android:versionCode="1"
android:versionName="1.0">
</manifest>`
const buildgradle = `buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 'android-19'
defaultConfig { minSdkVersion 16 }
}
repositories {
flatDir { dirs 'libs' }
}
dependencies {
implementation(name: "pkg", ext: "aar")
}
`
const stringsxml = `<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="dummy">dummy</string>
</resources>`

197
bind/objc/SeqBench.m Normal file
View file

@ -0,0 +1,197 @@
// Copyright 2015 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.
//go:build ignore
// +build ignore
#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>
#import "benchmark/Benchmark.h"
@interface AnI : NSObject <BenchmarkI> {
}
@end
@implementation AnI
- (void)f {
}
@end
@interface Benchmarks : NSObject <BenchmarkBenchmarks> {
}
@end
@implementation Benchmarks
- (void)manyargs:(long)p0 p1:(long)p1 p2:(long)p2 p3:(long)p3 p4:(long)p4 p5:(long)p5 p6:(long)p6 p7:(long)p7 p8:(long)p8 p9:(long)p9 {
}
- (id<BenchmarkI>)newI {
return [[AnI alloc] init];
}
- (void)noargs {
}
- (void)onearg:(long)p0 {
}
- (long)oneret {
return 0;
}
- (void)ref:(id<BenchmarkI>)p0 {
}
- (void)slice:(NSData*)p0 {
}
- (void)string:(NSString*)p0 {
}
- (NSString*)stringRetLong {
return BenchmarkLongString;
}
- (NSString*)stringRetShort {
return BenchmarkShortString;
}
- (void (^)(void))lookupBenchmark:(NSString *)name {
if ([name isEqualToString:@"Empty"]) {
return ^() {
};
} else if ([name isEqualToString:@"Noargs"]) {
return ^() {
BenchmarkNoargs();
};
} else if ([name isEqualToString:@"Onearg"]) {
return ^() {
BenchmarkOnearg(0);
};
} else if ([name isEqualToString:@"Manyargs"]) {
return ^() {
BenchmarkManyargs(0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
};
} else if ([name isEqualToString:@"Oneret"]) {
return ^() {
BenchmarkOneret();
};
} else if ([name isEqualToString:@"Refforeign"]) {
id<BenchmarkI> objcRef = [[AnI alloc] init];
return ^() {
BenchmarkRef(objcRef);
};
} else if ([name isEqualToString:@"Refgo"]) {
id<BenchmarkI> goRef = BenchmarkNewI();
return ^() {
BenchmarkRef(goRef);
};
} else if ([name isEqualToString:@"StringShort"]) {
return ^() {
BenchmarkString(BenchmarkShortString);
};
} else if ([name isEqualToString:@"StringLong"]) {
return ^() {
BenchmarkString(BenchmarkLongString);
};
} else if ([name isEqualToString:@"StringShortUnicode"]) {
return ^() {
BenchmarkString(BenchmarkShortStringUnicode);
};
} else if ([name isEqualToString:@"StringLongUnicode"]) {
return ^() {
BenchmarkString(BenchmarkLongStringUnicode);
};
} else if ([name isEqualToString:@"StringRetShort"]) {
return ^() {
BenchmarkStringRetShort();
};
} else if ([name isEqualToString:@"StringRetLong"]) {
return ^() {
BenchmarkStringRetLong();
};
} else if ([name isEqualToString:@"SliceShort"]) {
NSData *s = [Benchmark shortSlice];
return ^() {
BenchmarkSlice(s);
};
} else if ([name isEqualToString:@"SliceLong"]) {
NSData *s = [Benchmark longSlice];
return ^() {
BenchmarkSlice(s);
};
} else {
return nil;
}
}
- (void)run:(NSString*)name n:(long)n {
void (^bench)(void) = [self lookupBenchmark:name];
if (bench == nil) {
NSLog(@"Error: no such benchmark: %@", name);
return;
}
for (int i = 0; i < n; i++) {
bench();
}
}
- (void)runDirect:(NSString*)name n:(long)n {
void (^bench)(void) = [self lookupBenchmark:name];
if (bench == nil) {
NSLog(@"Error: no such benchmark: %@", name);
return;
}
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (int i = 0; i < n; i++) {
bench();
}
});
}
@end
@interface benchmarks : XCTestCase
@end
@implementation benchmarks
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
self.continueAfterFailure = NO;
// UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
[[[XCUIApplication alloc] init] launch];
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testBenchmark {
// Long running unit tests seem to hang. Use an XCTestExpectation and run the Go
// benchmark suite on a GCD thread.
XCTestExpectation *expectation =
[self expectationWithDescription:@"Benchmark"];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Benchmarks *b = [[Benchmarks alloc] init];
BenchmarkRunBenchmarks(b);
[expectation fulfill];
});
[self waitForExpectationsWithTimeout:5*60.0 handler:^(NSError *error) {
if (error) {
NSLog(@"Timeout Error: %@", error);
}
}];
}
@end

22
bind/objc/SeqCustom.m Normal file
View file

@ -0,0 +1,22 @@
// Copyright 2018 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.
//go:build ignore
// +build ignore
#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>
@import Testpkg;
@interface tests : XCTestCase
@end
@implementation tests
- (void)testBasics {
CustomTestpkgHi();
}
@end

481
bind/objc/SeqTest.m Normal file
View file

@ -0,0 +1,481 @@
// Copyright 2015 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.
//go:build ignore
// +build ignore
#import <Foundation/Foundation.h>
#import <XCTest/XCTest.h>
#import "testpkg/Testpkg.h"
// Objective-C implementation of testpkg.I2.
@interface Number : NSObject <TestpkgI2> {
}
@property int32_t value;
// TODO(hyangah): error:error is not good.
- (BOOL)error:(BOOL)e error:(NSError **)error;
- (int64_t)times:(int32_t)v;
@end
// numI is incremented when the first numI objective-C implementation is
// deallocated.
static int numI = 0;
@implementation Number {
}
@synthesize value;
- (NSString *)stringError:(NSString *)s
error:(NSError **)error {
if ([s isEqualToString:@"number"]) {
return @"OK";
}
*error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:@{NSLocalizedDescriptionKey: @"NumberError"}];
return NULL;
}
- (BOOL)error:(BOOL)triggerError error:(NSError **)error {
if (!triggerError) {
return YES;
}
if (error != NULL) {
*error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:NULL];
}
return NO;
}
- (int64_t)times:(int32_t)v {
return v * value;
}
- (void)dealloc {
if (self.value == 0) {
numI++;
}
}
@end
// Objective-C implementation of testpkg.NullTest.
@interface NullTest : NSObject <TestpkgNullTest> {
}
- (TestpkgNullTest *)null;
@end
@implementation NullTest {
}
- (TestpkgNullTest *)null {
return nil;
}
@end
// Objective-C implementation of testpkg.InterfaceDupper.
@interface IDup : NSObject <TestpkgInterfaceDupper> {
}
@end
@implementation IDup {
}
- (id<TestpkgInterface>)iDup:(id<TestpkgInterface>)i {
return i;
}
@end
// Objective-C implementation of testpkg.ConcreteDupper.
@interface CDup : NSObject <TestpkgConcreteDupper> {
}
@end
@implementation CDup {
}
- (TestpkgConcrete *)cDup:(TestpkgConcrete *)c {
return c;
}
@end
// Objective-C implementation of testpkg.EmptyThrower.
@interface EmptyErrorer: NSObject <TestpkgEmptyErrorer> {
}
@end
@implementation EmptyErrorer {
}
- (BOOL)emptyError:(NSError **)error {
*error = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:NULL];
return NO;
}
@end
@interface tests : XCTestCase
@end
@implementation tests
- (void)setUp {
[super setUp];
}
- (void)tearDown {
[super tearDown];
}
- (void)testBasics {
TestpkgHi();
TestpkgInt(42);
}
- (void)testAdd {
int64_t sum = TestpkgAdd(31, 21);
XCTAssertEqual(sum, 52, @"TestpkgSum(31, 21) = %lld, want 52\n", sum);
}
- (void)testHello:(NSString *)input {
NSString *got = TestpkgAppendHello(input);
NSString *want = [NSString stringWithFormat:@"Hello, %@!", input];
XCTAssertEqualObjects(got, want, @"want %@\nTestpkgHello(%@)= %@", want, input, got);
}
- (void)testHellos {
[self testHello:@"세계"]; // korean, utf-8, world.
unichar t[] = {
0xD83D, 0xDCA9,
}; // utf-16, pile of poo.
[self testHello:[NSString stringWithCharacters:t length:2]];
}
- (void)testString {
NSString *input = @"";
NSString *got = TestpkgStrDup(input);
XCTAssertEqualObjects(got, input, @"want %@\nTestpkgEcho(%@)= %@", input, input, got);
input = @"FOO";
got = TestpkgStrDup(input);
XCTAssertEqualObjects(got, input, @"want %@\nTestpkgEcho(%@)= %@", input, input, got);
}
- (void)testStruct {
TestpkgS2 *s = TestpkgNewS2(10.0, 100.0);
XCTAssertNotNil(s, @"TestpkgNewS2 returned NULL");
double x = [s x];
double y = [s y];
double sum = [s sum];
XCTAssertTrue(x == 10.0 && y == 100.0 && sum == 110.0,
@"TestpkgS2(10.0, 100.0).X=%f Y=%f SUM=%f; want 10, 100, 110", x, y, sum);
double sum2 = TestpkgCallSSum(s);
XCTAssertEqual(sum, sum2, @"TestpkgCallSSum(s)=%f; want %f as returned by s.Sum", sum2, sum);
[s setX:7];
[s setY:70];
x = [s x];
y = [s y];
sum = [s sum];
XCTAssertTrue(x == 7 && y == 70 && sum == 77,
@"TestpkgS2(7, 70).X=%f Y=%f SUM=%f; want 7, 70, 77", x, y, sum);
NSString *first = @"trytwotested";
NSString *second = @"test";
NSString *got = [s tryTwoStrings:first second:second];
NSString *want = [first stringByAppendingString:second];
XCTAssertEqualObjects(got, want, @"TestpkgS_TryTwoStrings(%@, %@)= %@; want %@", first, second, got, want);
}
- (void)testCollectS {
@autoreleasepool {
[self testStruct];
}
TestpkgGC();
long numS = TestpkgCollectS2(
1, 10); // within 10 seconds, collect the S used in testStruct.
XCTAssertEqual(numS, 1, @"%ld S objects were collected; S used in testStruct is supposed to "
@"be collected.",
numS);
}
- (void)testBytesAppend {
NSString *a = @"Foo";
NSString *b = @"Bar";
NSData *data_a = [a dataUsingEncoding:NSUTF8StringEncoding];
NSData *data_b = [b dataUsingEncoding:NSUTF8StringEncoding];
NSData *gotData = TestpkgBytesAppend(data_a, data_b);
NSString *got = [[NSString alloc] initWithData:gotData encoding:NSUTF8StringEncoding];
NSString *want = [a stringByAppendingString:b];
XCTAssertEqualObjects(got, want, @"want %@\nTestpkgBytesAppend(%@, %@) = %@", want, a, b, got);
}
- (void)testInterface {
// Test Go object implementing testpkg.I is handled correctly.
id<TestpkgI2> goObj = TestpkgNewI();
int64_t got = [goObj times:10];
XCTAssertEqual(got, 100, @"TestpkgNewI().times(10) = %lld; want %d", got, 100);
int32_t key = -1;
TestpkgRegisterI(key, goObj);
int64_t got2 = TestpkgMultiply(key, 10);
XCTAssertEqual(got, got2, @"TestpkgMultiply(10 * 10) = %lld; want %lld", got2, got);
TestpkgUnregisterI(key);
// Test Objective-C objects implementing testpkg.I is handled correctly.
@autoreleasepool {
for (int32_t i = 0; i < 10; i++) {
Number *num = [[Number alloc] init];
num.value = i;
TestpkgRegisterI(i, num);
}
TestpkgGC();
}
// Registered Objective-C objects are pinned on Go side which must
// prevent deallocation from Objective-C.
for (int32_t i = 0; i < 10; i++) {
int64_t got = TestpkgMultiply(i, 2);
XCTAssertEqual(got, i * 2,@"TestpkgMultiply(%d, 2) = %lld; want %d", i, got, i * 2);
TestpkgUnregisterI(i);
TestpkgGC();
}
// Unregistered all Objective-C objects.
}
- (void)testCollectI {
@autoreleasepool {
[self testInterface];
}
XCTAssertEqual(numI, 1, @"%d I objects were collected; I used in testInterface is supposed "
@"to be collected.", numI);
}
- (void)testConst {
XCTAssertEqualObjects(TestpkgAString, @"a string", @"TestpkgAString = %@, want 'a string'", TestpkgAString);
XCTAssertEqual(TestpkgAnInt, 7, @"TestpkgAnInt = %lld, want 7", TestpkgAnInt);
XCTAssertTrue(ABS(TestpkgAFloat - 0.12345) < 0.0001, @"TestpkgAFloat = %f, want 0.12345", TestpkgAFloat);
XCTAssertTrue(TestpkgABool == YES, @"TestpkgABool = %@, want YES", TestpkgAFloat ? @"YES" : @"NO");
XCTAssertEqual(TestpkgMinInt32, INT32_MIN, @"TestpkgMinInt32 = %d, want %d", TestpkgMinInt32, INT32_MIN);
XCTAssertEqual(TestpkgMaxInt32, INT32_MAX, @"TestpkgMaxInt32 = %d, want %d", TestpkgMaxInt32, INT32_MAX);
XCTAssertEqual(TestpkgMinInt64, INT64_MIN, @"TestpkgMinInt64 = %lld, want %lld", TestpkgMinInt64, INT64_MIN);
XCTAssertEqual(TestpkgMaxInt64, INT64_MAX, @"TestpkgMaxInt64 = %lld, want %lld", TestpkgMaxInt64, INT64_MAX);
XCTAssertTrue(ABS(TestpkgSmallestNonzeroFloat64 -
4.940656458412465441765687928682213723651e-324) < 1e-323, @"TestpkgSmallestNonzeroFloat64 = %f, want %f",
TestpkgSmallestNonzeroFloat64,
4.940656458412465441765687928682213723651e-324);
XCTAssertTrue(ABS(TestpkgMaxFloat64 -
1.797693134862315708145274237317043567981e+308) < 0.0001, @"TestpkgMaxFloat64 = %f, want %f", TestpkgMaxFloat64,
1.797693134862315708145274237317043567981e+308);
XCTAssertTrue(ABS(TestpkgSmallestNonzeroFloat32 -
1.401298464324817070923729583289916131280e-45) < 1e-44, @"TestpkgSmallestNonzeroFloat32 = %f, want %f",
TestpkgSmallestNonzeroFloat32,
1.401298464324817070923729583289916131280e-45);
XCTAssertTrue(ABS(TestpkgMaxFloat32 - 3.40282346638528859811704183484516925440e+38) < 0.0001,
@"TestpkgMaxFloat32 = %f, want %f", TestpkgMaxFloat32, 3.40282346638528859811704183484516925440e+38);
XCTAssertTrue(ABS(TestpkgLog2E - 1 / 0.693147180559945309417232121458176568075500134360255254120680009) < 0.0001,
@"TestpkgLog2E = %f, want %f", TestpkgLog2E, 1 / 0.693147180559945309417232121458176568075500134360255254120680009);
}
- (void)testIssue12307 {
Number *num = [[Number alloc] init];
num.value = 1024;
NSError *error;
XCTAssertFalse(TestpkgCallIError(num, YES, &error), @"TestpkgCallIError(Number, YES) succeeded; want error");
NSError *error2;
XCTAssertTrue(TestpkgCallIError(num, NO, &error2), @"TestpkgCallIError(Number, NO) failed(%@); want success", error2);
}
- (void)testErrorField {
NSString *wantMsg = @"an error message";
NSError *want = [NSError errorWithDomain:@"SeqTest" code:1 userInfo:@{NSLocalizedDescriptionKey: wantMsg}];
TestpkgNode *n = TestpkgNewNode(@"ErrTest");
n.err = want;
NSError *got = n.err;
XCTAssertEqual(got, want, @"got different objects after roundtrip");
NSString *gotMsg = TestpkgErrorMessage(want);
XCTAssertEqualObjects(gotMsg, wantMsg, @"err = %@, want %@", gotMsg, wantMsg);
}
- (void)testErrorDup {
NSError *err = Testpkg.globalErr;
XCTAssertTrue(TestpkgIsGlobalErr(err), @"A Go error must preserve its identity across the boundary");
XCTAssertEqualObjects([err localizedDescription], @"global err", "A Go error message must be preserved");
}
- (void)testVar {
NSString *s = Testpkg.stringVar;
XCTAssertEqualObjects(s, @"a string var", @"Testpkg.StringVar = %@, want 'a string var'", s);
s = @"a new string var";
Testpkg.stringVar = s;
NSString *s2 = Testpkg.stringVar;
XCTAssertEqualObjects(s2, s, @"Testpkg.stringVar = %@, want %@", s2, s);
int64_t i = Testpkg.intVar;
XCTAssertEqual(i, 77, @"Testpkg.intVar = %lld, want 77", i);
Testpkg.intVar = 777;
i = Testpkg.intVar;
XCTAssertEqual(i, 777, @"Testpkg.intVar = %lld, want 777", i);
[Testpkg setIntVar:7777];
i = [Testpkg intVar];
XCTAssertEqual(i, 7777, @"Testpkg.intVar = %lld, want 7777", i);
TestpkgNode *n0 = Testpkg.nodeVar;
XCTAssertEqualObjects(n0.v, @"a struct var", @"Testpkg.NodeVar = %@, want 'a struct var'", n0.v);
TestpkgNode *n1 = TestpkgNewNode(@"a new struct var");
Testpkg.nodeVar = n1;
TestpkgNode *n2 = Testpkg.nodeVar;
XCTAssertEqualObjects(n2.v, @"a new struct var", @"Testpkg.NodeVar = %@, want 'a new struct var'", n2.v);
Number *num = [[Number alloc] init];
num.value = 12345;
Testpkg.interfaceVar2 = num;
id<TestpkgI2> iface = Testpkg.interfaceVar2;
int64_t x = [iface times:10];
int64_t y = [num times:10];
XCTAssertEqual(x, y, @"Testpkg.InterfaceVar2 Times 10 = %lld, want %lld", x, y);
}
- (void)testIssue12403 {
Number *num = [[Number alloc] init];
num.value = 1024;
NSError *error;
NSString *ret = TestpkgCallIStringError(num, @"alphabet", &error);
XCTAssertNil(ret, @"TestpkgCallIStringError(Number, 'alphabet') succeeded(%@); want error", ret);
NSString *desc = [error localizedDescription];
XCTAssertEqualObjects(desc, @"NumberError", @"TestpkgCallIStringError(Number, 'alphabet') returned unexpected error message %@", desc);
NSError *error2;
NSString *ret2 = TestpkgCallIStringError(num, @"number", &error2);
XCTAssertNotNil(ret2, @"TestpkgCallIStringError(Number, 'number') failed(%@); want success", error2);
XCTAssertEqualObjects(ret2, @"OK", @"TestpkgCallIStringError(Number, 'number') returned unexpected results %@", ret2);
}
- (void)testStrDup:(NSString *)want {
NSString *got = TestpkgStrDup(want);
XCTAssertEqualObjects(want, got, @"StrDup returned %@; expected %@", got, want);
}
- (void)testUnicodeStrings {
[self testStrDup:@"abcxyz09{}"];
[self testStrDup:@"Hello, 世界"];
[self testStrDup:@"\uffff\U00010000\U00010001\U00012345\U0010ffff"];
}
- (void)testByteArrayRead {
NSData *arr = [NSMutableData dataWithLength:8];
long n;
XCTAssertTrue(TestpkgReadIntoByteArray(arr, &n, nil), @"ReadIntoByteArray failed");
XCTAssertEqual(n, 8, @"ReadIntoByteArray wrote %ld bytes, expected %d", n, 8);
const uint8_t *b = [arr bytes];
for (int i = 0; i < [arr length]; i++) {
XCTAssertEqual(b[i], i, @"ReadIntoByteArray wrote %d at %d; expected %d", b[i], i, i);
}
// Test that immutable data cannot be changed from Go
const uint8_t buf[] = {42};
arr = [NSData dataWithBytes:buf length:1];
XCTAssertTrue(TestpkgReadIntoByteArray(arr, &n, nil), @"ReadIntoByteArray failed");
XCTAssertEqual(n, 1, @"ReadIntoByteArray wrote %ld bytes, expected %d", n, 8);
b = [arr bytes];
XCTAssertEqual(b[0], 42, @"ReadIntoByteArray wrote to an immutable NSData; expected no change");
}
- (void)testNilField {
TestpkgNullFieldStruct *s = TestpkgNewNullFieldStruct();
XCTAssertNil([s f], @"NullFieldStruct has non-nil field; expected nil");
}
- (void)testNullReferences {
NullTest *t = [[NullTest alloc] init];
XCTAssertTrue(TestpkgCallWithNull(nil, t), @"Testpkg.CallWithNull failed");
id<TestpkgI> i = TestpkgNewNullInterface();
XCTAssertNil(i, @"NewNullInterface() returned %p; expected nil", i);
TestpkgS *s = TestpkgNewNullStruct();
XCTAssertNil(s, @"NewNullStruct() returned %p; expected nil", s);
TestpkgIssue20330 *nullArger = TestpkgNewIssue20330();
XCTAssertTrue([nullArger callWithNull:nil], @"Issue20330.CallWithNull failed");
}
- (void)testReturnsError {
NSError *error;
NSString *value = TestpkgReturnsError(TRUE, &error);
NSString *got = [error.userInfo valueForKey:NSLocalizedDescriptionKey];
NSString *want = @"Error";
XCTAssertEqualObjects(got, want, @"want %@\nTestpkgReturnsError(TRUE) = (%@, %@)", want, value, got);
}
- (void)testImportedPkg {
XCTAssertEqualObjects(SecondpkgHelloString, SecondpkgHello(), @"imported string should match");
id<SecondpkgI> i = TestpkgNewImportedI();
SecondpkgS *s = TestpkgNewImportedS();
XCTAssertEqual(8, [i f:8], @"numbers should match");
XCTAssertEqual(8, [s f:8], @"numbers should match");
i = TestpkgWithImportedI(i);
s = TestpkgWithImportedS(s);
i = [Testpkg importedVarI];
s = [Testpkg importedVarS];
[Testpkg setImportedVarI:i];
[Testpkg setImportedVarS:s];
TestpkgImportedFields *fields = TestpkgNewImportedFields();
i = [fields i];
s = [fields s];
[fields setI:i];
[fields setS:s];
}
- (void)testRoundTripEquality {
Number *want = [[Number alloc] init];
Number *got = (Number *)TestpkgI2Dup(want);
XCTAssertEqual(got, want, @"ObjC object passed through Go should not be wrapped");
IDup *idup = [[IDup alloc] init];
XCTAssertTrue(TestpkgCallIDupper(idup), @"Go interface passed through ObjC should not be wrapped");
CDup *cdup = [[CDup alloc] init];
XCTAssertTrue(TestpkgCallCDupper(cdup), @"Go struct passed through ObjC should not be wrapped");
}
- (void)testEmptyError {
NSError *error;
XCTAssertFalse(TestpkgEmptyError(&error), @"GoTestpkgEmptyError succeeded; want error");
XCTAssertNotNil(error, @"TestpkgEmptyError returned nil error");
id<TestpkgEmptyErrorer> empty = [[EmptyErrorer alloc] init];
XCTAssertFalse(TestpkgCallEmptyError(empty, &error), @"TestpkgCallEmptyError succeeded; want error");
XCTAssertNotNil(error, @"TestpkgCallEmptyError returned nil error");
}
- (void)testSIGPIPE {
TestpkgTestSIGPIPE();
}
- (void)testTags {
XCTAssertEqual(42, TestpkgTaggedConst, @"Tagged const must exist");
}
- (void)testConstructors {
id<TestpkgInterface> i = [[TestpkgConcrete alloc] init];
[i f];
TestpkgS2 *s = [[TestpkgS2 alloc] init:1 y:2];
XCTAssertEqual(3.0, [s sum]);
XCTAssertEqualObjects(@"gostring", [s tryTwoStrings:@"go" second:@"string"]);
TestpkgS3 *s3 __attribute__((unused)) = [[TestpkgS3 alloc] init];
TestpkgS4 *s4 = [[TestpkgS4 alloc] initWithInt:123];
XCTAssertEqual(123, s4.i);
s4 = [[TestpkgS4 alloc] initWithFloat: 123.456];
XCTAssertEqual(123, s4.i);
s4 = [[TestpkgS4 alloc] initWithBoolAndError: false];
XCTAssertEqual(0, s4.i);
s4 = [[TestpkgS4 alloc] initWithBoolAndError: true];
XCTAssertEqual(s4, NULL);
}
@end

98
bind/objc/SeqWrappers.m Normal file
View file

@ -0,0 +1,98 @@
// Copyright 2015 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.
//go:build ignore
// +build ignore
@import ObjectiveC.message;
@import Foundation;
@import XCTest;
@import Objcpkg;
@interface TestNSObject : NSObject
- (NSString *)description;
- (NSString *)super_description;
@end
@implementation TestNSObject
- (NSString *)description {
return @"hej";
}
- (NSString *)super_description {
return [super description];
}
@end
@interface wrappers : XCTestCase
@end
@implementation wrappers
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testFunction {
ObjcpkgFunc();
}
- (void)testMethod {
ObjcpkgMethod();
}
- (void)testNew {
ObjcpkgNew();
}
- (void)testError {
ObjcpkgError();
}
- (void)testClass {
ObjcpkgGoNSDate *d = [[ObjcpkgGoNSDate alloc] init];
NSString *desc = [d description];
XCTAssertEqual(d, [d getSelf], "GoNSDate self not identical");
XCTAssertEqual(ObjcpkgHash, [d hash], "GoNSDate hash not identical");
XCTAssertTrue([desc isEqualToString:ObjcpkgDescriptionStr], "GoNSDate description mismatch: %@", desc);
ObjcpkgGoUIResponder *resp = [[ObjcpkgGoUIResponder alloc] init];
[resp pressesBegan:nil withEvent:nil];
XCTAssertTrue([resp called], "GoUIResponder.pressesBegan not called");
}
- (void)testSuper {
ObjcpkgGoNSObject *o = [[ObjcpkgGoNSObject alloc] init];
struct objc_super _super = {
.receiver = o,
.super_class = [NSObject class],
};
NSString *superDesc = ((NSString *(*)(struct objc_super*, SEL))objc_msgSendSuper)(&_super, @selector(description));
XCTAssertTrue([superDesc isEqualToString:[o description]], "GoNSObject description mismatch");
[o setUseSelf:TRUE];
XCTAssertTrue([ObjcpkgDescriptionStr isEqualToString:[o description]], "GoNSObject description mismatch");
}
- (void)testIdentity {
NSDate *d = [[NSDate alloc] init];
NSDate *d2 = ObjcpkgDupNSDate(d);
XCTAssertEqual(d, d2, @"ObjcpkgDupNSDate failed to duplicate ObjC instance");
ObjcpkgGoNSDate *gd = [[ObjcpkgGoNSDate alloc] init];
NSDate *gd2 = ObjcpkgDupNSDate(gd);
XCTAssertEqual(gd, gd2, @"ObjcpkgDupNSDate failed to duplicate Go instance");
NSDate *gd3 = ObjcpkgNewGoNSDate();
NSDate *gd4 = ObjcpkgDupNSDate(gd3);
XCTAssertEqual(gd4, gd3, @"ObjcpkgDupNSDate failed to duplicate instance created in Go");
}
@end

6
bind/objc/doc.go Normal file
View file

@ -0,0 +1,6 @@
// Copyright 2015 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 objc implements the Objective-C language bindings.
package objc

35
bind/objc/ref.h Normal file
View file

@ -0,0 +1,35 @@
// Copyright 2015 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.
#ifndef __GO_REF_HDR__
#define __GO_REF_HDR__
#include <Foundation/Foundation.h>
// GoSeqRef is an object tagged with an integer for passing back and
// forth across the language boundary. A GoSeqRef may represent either
// an instance of a Go object, or an Objective-C object passed to Go.
// The explicit allocation of a GoSeqRef is used to pin a Go object
// when it is passed to Objective-C. The Go seq package maintains a
// reference to the Go object in a map keyed by the refnum along with
// a reference count. When the reference count reaches zero, the Go
// seq package will clear the corresponding entry in the map.
@interface GoSeqRef : NSObject {
}
@property(readonly) int32_t refnum;
@property(strong) id obj; // NULL when representing a Go object.
// new GoSeqRef object to proxy a Go object. The refnum must be
// provided from Go side.
- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
- (int32_t)incNum;
@end
@protocol goSeqRefInterface
-(GoSeqRef*) _ref;
@end
#endif

View file

@ -0,0 +1,91 @@
// 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 main
// Go support functions for Objective-C. Note that this
// file is copied into and compiled with the generated
// bindings.
/*
#cgo CFLAGS: -x objective-c -fobjc-arc -fmodules -fblocks -Werror
#cgo LDFLAGS: -framework Foundation
#include <stdint.h>
#include <stdlib.h>
#include "seq.h"
*/
import "C"
import (
"unsafe"
"golang.org/x/mobile/bind/seq"
)
// DestroyRef is called by Objective-C to inform Go it is done with a reference.
//export DestroyRef
func DestroyRef(refnum C.int32_t) {
seq.Delete(int32(refnum))
}
// encodeString copies a Go string and returns it as a nstring.
func encodeString(s string) C.nstring {
n := C.int(len(s))
if n == 0 {
return C.nstring{}
}
ptr := C.malloc(C.size_t(n))
if ptr == nil {
panic("encodeString: malloc failed")
}
copy((*[1<<31 - 1]byte)(ptr)[:n], s)
return C.nstring{ptr: ptr, len: n}
}
// decodeString converts a nstring to a Go string. The
// data in str is freed after use.
func decodeString(str C.nstring) string {
if str.ptr == nil {
return ""
}
s := C.GoStringN((*C.char)(str.ptr), str.len)
C.free(str.ptr)
return s
}
// fromSlice converts a slice to a nbyteslice.
// If cpy is set, a malloc'ed copy of the data is returned.
func fromSlice(s []byte, cpy bool) C.nbyteslice {
if s == nil || len(s) == 0 {
return C.nbyteslice{}
}
ptr, n := unsafe.Pointer(&s[0]), C.int(len(s))
if cpy {
nptr := C.malloc(C.size_t(n))
if nptr == nil {
panic("fromSlice: malloc failed")
}
copy((*[1<<31 - 1]byte)(nptr)[:n], (*[1<<31 - 1]byte)(ptr)[:n])
ptr = nptr
}
return C.nbyteslice{ptr: ptr, len: n}
}
// toSlice takes a nbyteslice and returns a byte slice with the data. If cpy is
// set, the slice contains a copy of the data. If not, the generated Go code
// calls releaseByteSlice after use.
func toSlice(s C.nbyteslice, cpy bool) []byte {
if s.ptr == nil || s.len == 0 {
return nil
}
var b []byte
if cpy {
b = C.GoBytes(s.ptr, C.int(s.len))
C.free(s.ptr)
} else {
b = (*[1<<31 - 1]byte)(unsafe.Pointer(s.ptr))[:s.len:s.len]
}
return b
}

63
bind/objc/seq_darwin.h Normal file
View file

@ -0,0 +1,63 @@
// Copyright 2015 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.
#ifndef __GO_SEQ_DARWIN_HDR__
#define __GO_SEQ_DARWIN_HDR__
#include <Foundation/Foundation.h>
#include "ref.h"
#include "Universe.objc.h"
#ifdef DEBUG
#define LOG_DEBUG(...) NSLog(__VA_ARGS__);
#else
#define LOG_DEBUG(...) ;
#endif
#define LOG_INFO(...) NSLog(__VA_ARGS__);
#define LOG_FATAL(...) \
{ \
NSLog(__VA_ARGS__); \
@throw \
[NSException exceptionWithName:NSInternalInconsistencyException \
reason:[NSString stringWithFormat:__VA_ARGS__] \
userInfo:NULL]; \
}
// Platform specific types
typedef struct nstring {
void *ptr;
int len;
} nstring;
typedef struct nbyteslice {
void *ptr;
int len;
} nbyteslice;
typedef int nint;
extern void init_seq();
// go_seq_dec_ref decrements the reference count for the
// specified refnum. It is called from Go from a finalizer.
extern void go_seq_dec_ref(int32_t refnum);
// go_seq_inc_ref increments the reference count for the
// specified refnum. It is called from Go just before converting
// a proxy to its refnum.
extern void go_seq_inc_ref(int32_t refnum);
extern int32_t go_seq_to_refnum(id obj);
// go_seq_go_to_refnum is a special case of go_seq_to_refnum
extern int32_t go_seq_go_to_refnum(GoSeqRef *ref);
extern GoSeqRef *go_seq_from_refnum(int32_t refnum);
// go_seq_objc_from_refnum is a special case of go_seq_from_refnum for
// Objective-C objects that implement a Go interface.
extern id go_seq_objc_from_refnum(int32_t refnum);
extern nbyteslice go_seq_from_objc_bytearray(NSData *data, int copy);
extern nstring go_seq_from_objc_string(NSString *s);
extern NSData *go_seq_to_objc_bytearray(nbyteslice, int copy);
extern NSString *go_seq_to_objc_string(nstring str);
#endif // __GO_SEQ_DARWIN_HDR__

View file

@ -0,0 +1,381 @@
// 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.
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
// * Objective-C implementation of a Go interface type
//
// For an interface testpkg.I, gobind defines a protocol GoSeqTestpkgI.
// Reference tracker (tracker) maintains two maps:
// 1) _refs: objective-C object pointer -> a refnum (starting from 42).
// 2) _objs: refnum -> RefCounter.
//
// Whenever a user's object conforming the protocol is sent to Go (through
// a function or method that takes I), _refs is consulted to find the refnum
// of the object. If not found, the refnum is assigned and stored.
//
// _objs is also updated so that the RefCounter is incremented and the
// user's object is pinned.
//
// When a Go side needs to call a method of the interface, the Go side
// notifies the Objective-C side of the object's refnum. Upon receiving the
// request, Objective-C side looks up the object from _objs map, and sends
// the method to the object.
//
// The RefCount counts the references on objective-C objects from Go side,
// and pins the objective-C objects until there is no more references from
// Go side.
//
// * Objective-C proxy of a Go object (struct or interface type)
//
// For Go type object, a objective-C proxy instance is created whenever
// the object reference is passed into objective-C.
//
// While crossing the language barrier there is a brief window where the foreign
// proxy object might be finalized but the refnum is not yet translated to its object.
// If the proxy object was the last reference to the foreign object, the refnum
// will be invalid by the time it is looked up in the foreign reference tracker.
//
// To make sure the foreign object is kept live while its refnum is in transit,
// increment its refererence count before crossing. The other side will decrement
// it again immediately after the refnum is converted to its object.
// Note that this file is copied into and compiled with the generated
// bindings.
// A simple thread-safe mutable dictionary.
@interface goSeqDictionary : NSObject {
}
@property NSMutableDictionary *dict;
@end
@implementation goSeqDictionary
- (id)init {
if (self = [super init]) {
_dict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (id)get:(id)key {
@synchronized(self) {
return [_dict objectForKey:key];
}
}
- (void)put:(id)obj withKey:(id)key {
@synchronized(self) {
[_dict setObject:obj forKey:key];
}
}
@end
// NULL_REFNUM is also known to bind/seq/ref.go and bind/java/Seq.java
#define NULL_REFNUM 41
// RefTracker encapsulates a map of objective-C objects passed to Go and
// the reference number counter which is incremented whenever an objective-C
// object that implements a Go interface is created.
@interface RefTracker : NSObject {
int32_t _next;
NSMutableDictionary *_refs; // map: object ptr -> refnum
NSMutableDictionary *_objs; // map: refnum -> RefCounter*
}
- (id)init;
// decrements the counter of the objective-C object with the reference number.
// This is called whenever a Go proxy to this object is finalized.
// When the counter reaches 0, the object is removed from the map.
- (void)dec:(int32_t)refnum;
// increments the counter of the objective-C object with the reference number.
// This is called whenever a Go proxy is converted to its refnum and send
// across the language barrier.
- (void)inc:(int32_t)refnum;
// returns the object of the reference number.
- (id)get:(int32_t)refnum;
// returns the reference number of the object and increments the ref count.
// This is called whenever an Objective-C object is sent to Go side.
- (int32_t)assignRefnumAndIncRefcount:(id)obj;
@end
static RefTracker *tracker = NULL;
#define IS_FROM_GO(refnum) ((refnum) < 0)
// init_seq is called when the Go side is initialized.
void init_seq() { tracker = [[RefTracker alloc] init]; }
void go_seq_dec_ref(int32_t refnum) {
@autoreleasepool {
[tracker dec:refnum];
}
}
void go_seq_inc_ref(int32_t refnum) {
@autoreleasepool {
[tracker inc:refnum];
}
}
NSData *go_seq_to_objc_bytearray(nbyteslice s, int copy) {
if (s.ptr == NULL) {
return NULL;
}
BOOL freeWhenDone = copy ? YES : NO;
return [NSData dataWithBytesNoCopy:s.ptr length:s.len freeWhenDone:freeWhenDone];
}
NSString *go_seq_to_objc_string(nstring str) {
if (str.len == 0) { // empty string.
return @"";
}
NSString * res = [[NSString alloc] initWithBytesNoCopy:str.ptr
length:str.len
encoding:NSUTF8StringEncoding
freeWhenDone:YES];
return res;
}
id go_seq_objc_from_refnum(int32_t refnum) {
id obj = [tracker get:refnum];
// Go called IncForeignRef just before converting its proxy to its refnum. Decrement it here.
// It's very important to decrement *after* fetching the reference from the tracker, in case
// there are no other proxy references to the object.
[tracker dec:refnum];
return obj;
}
GoSeqRef *go_seq_from_refnum(int32_t refnum) {
if (refnum == NULL_REFNUM) {
return nil;
}
if (IS_FROM_GO(refnum)) {
return [[GoSeqRef alloc] initWithRefnum:refnum obj:NULL];
}
return [[GoSeqRef alloc] initWithRefnum:refnum obj:go_seq_objc_from_refnum(refnum)];
}
int32_t go_seq_to_refnum(id obj) {
if (obj == nil) {
return NULL_REFNUM;
}
return [tracker assignRefnumAndIncRefcount:obj];
}
int32_t go_seq_go_to_refnum(GoSeqRef *ref) {
int32_t refnum = [ref incNum];
if (!IS_FROM_GO(refnum)) {
LOG_FATAL(@"go_seq_go_to_refnum on objective-c objects is not permitted");
}
return refnum;
}
nbyteslice go_seq_from_objc_bytearray(NSData *data, int copy) {
struct nbyteslice res = {NULL, 0};
int sz = data.length;
if (sz == 0) {
return res;
}
void *ptr;
// If the argument was not a NSMutableData, copy the data so that
// the NSData is not changed from Go. The corresponding free is called
// by releaseByteSlice.
if (copy || ![data isKindOfClass:[NSMutableData class]]) {
void *arr_copy = malloc(sz);
if (arr_copy == NULL) {
LOG_FATAL(@"malloc failed");
}
memcpy(arr_copy, [data bytes], sz);
ptr = arr_copy;
} else {
ptr = (void *)[data bytes];
}
res.ptr = ptr;
res.len = sz;
return res;
}
nstring go_seq_from_objc_string(NSString *s) {
nstring res = {NULL, 0};
int len = [s lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
if (len == 0) {
if (s.length > 0) {
LOG_INFO(@"unable to encode an NSString into UTF-8");
}
return res;
}
char *buf = (char *)malloc(len);
if (buf == NULL) {
LOG_FATAL(@"malloc failed");
}
NSUInteger used;
[s getBytes:buf
maxLength:len
usedLength:&used
encoding:NSUTF8StringEncoding
options:0
range:NSMakeRange(0, [s length])
remainingRange:NULL];
res.ptr = buf;
res.len = used;
return res;
}
@implementation GoSeqRef {
}
- (id)init {
LOG_FATAL(@"GoSeqRef init is disallowed");
}
- (int32_t)incNum {
IncGoRef(_refnum);
return _refnum;
}
// called when an object from Go is passed in.
- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj {
self = [super init];
if (self) {
_refnum = refnum;
_obj = obj;
}
return self;
}
- (void)dealloc {
if (IS_FROM_GO(_refnum)) {
DestroyRef(_refnum);
}
}
@end
// RefCounter is a pair of (GoSeqProxy, count). GoSeqProxy has a strong
// reference to an Objective-C object. The count corresponds to
// the number of Go proxy objects.
//
// RefTracker maintains a map of refnum to RefCounter, for every
// Objective-C objects passed to Go. This map allows the transact
// call to relay the method call to the right Objective-C object, and
// prevents the Objective-C objects from being deallocated
// while they are still referenced from Go side.
@interface RefCounter : NSObject {
}
@property(strong, readonly) id obj;
@property int cnt;
- (id)initWithObject:(id)obj;
@end
@implementation RefCounter {
}
- (id)initWithObject:(id)obj {
self = [super init];
if (self) {
_obj = obj;
_cnt = 0;
}
return self;
}
@end
@implementation RefTracker {
}
- (id)init {
self = [super init];
if (self) {
_next = 42;
_refs = [[NSMutableDictionary alloc] init];
_objs = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)dec:(int32_t)refnum { // called whenever a go proxy object is finalized.
if (IS_FROM_GO(refnum)) {
LOG_FATAL(@"dec:invalid refnum for Objective-C objects");
}
@synchronized(self) {
id key = @(refnum);
RefCounter *counter = [_objs objectForKey:key];
if (counter == NULL) {
LOG_FATAL(@"unknown refnum");
}
int n = counter.cnt;
if (n <= 0) {
LOG_FATAL(@"refcount underflow");
} else if (n == 1) {
LOG_DEBUG(@"remove the reference %d", refnum);
NSValue *ptr = [NSValue valueWithPointer:(const void *)(counter.obj)];
[_refs removeObjectForKey:ptr];
[_objs removeObjectForKey:key];
} else {
counter.cnt = n - 1;
}
}
}
// inc is called whenever a ObjC refnum crosses from Go to ObjC
- (void)inc:(int32_t)refnum {
if (IS_FROM_GO(refnum)) {
LOG_FATAL(@"dec:invalid refnum for Objective-C objects");
}
@synchronized(self) {
id key = @(refnum);
RefCounter *counter = [_objs objectForKey:key];
if (counter == NULL) {
LOG_FATAL(@"unknown refnum");
}
counter.cnt++;
}
}
- (id)get:(int32_t)refnum {
if (IS_FROM_GO(refnum)) {
LOG_FATAL(@"get:invalid refnum for Objective-C objects");
}
@synchronized(self) {
RefCounter *counter = _objs[@(refnum)];
if (counter == NULL) {
LOG_FATAL(@"unidentified object refnum: %d", refnum);
}
return counter.obj;
}
}
- (int32_t)assignRefnumAndIncRefcount:(id)obj {
@synchronized(self) {
NSValue *ptr = [NSValue valueWithPointer:(const void *)(obj)];
NSNumber *refnum = [_refs objectForKey:ptr];
if (refnum == NULL) {
refnum = @(_next++);
_refs[ptr] = refnum;
}
RefCounter *counter = [_objs objectForKey:refnum];
if (counter == NULL) {
counter = [[RefCounter alloc] initWithObject:obj];
counter.cnt = 1;
_objs[refnum] = counter;
} else {
counter.cnt++;
}
return (int32_t)([refnum intValue]);
}
}
@end

1009
bind/objc/seq_test.go Normal file

File diff suppressed because it is too large Load diff

67
bind/printer.go Normal file
View file

@ -0,0 +1,67 @@
// Copyright 2014 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 bind
import (
"bytes"
"fmt"
)
type Printer struct {
Buf *bytes.Buffer
IndentEach []byte
indentText []byte
needIndent bool
}
func (p *Printer) writeIndent() error {
if !p.needIndent {
return nil
}
p.needIndent = false
_, err := p.Buf.Write(p.indentText)
return err
}
func (p *Printer) Write(b []byte) (n int, err error) {
wrote := 0
for len(b) > 0 {
if err := p.writeIndent(); err != nil {
return wrote, err
}
i := bytes.IndexByte(b, '\n')
if i < 0 {
break
}
n, err = p.Buf.Write(b[0 : i+1])
wrote += n
if err != nil {
return wrote, err
}
b = b[i+1:]
p.needIndent = true
}
if len(b) > 0 {
n, err = p.Buf.Write(b)
wrote += n
}
return wrote, err
}
func (p *Printer) Printf(format string, args ...interface{}) {
if _, err := fmt.Fprintf(p, format, args...); err != nil {
panic(fmt.Sprintf("printer: %v", err))
}
}
func (p *Printer) Indent() {
p.indentText = append(p.indentText, p.IndentEach...)
}
func (p *Printer) Outdent() {
if len(p.indentText) > len(p.IndentEach)-1 {
p.indentText = p.indentText[len(p.IndentEach):]
}
}

52
bind/seq.go.support Normal file
View file

@ -0,0 +1,52 @@
// 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 main
// Go support functions for generated Go bindings. This file is
// copied into the generated main package, and compiled along
// with the bindings.
// #cgo android CFLAGS: -D__GOBIND_ANDROID__
// #cgo darwin CFLAGS: -D__GOBIND_DARWIN__
// #include <stdlib.h>
// #include "seq.h"
import "C"
import (
"fmt"
"os"
"os/signal"
"syscall"
_ "golang.org/x/mobile/bind/java"
_seq "golang.org/x/mobile/bind/seq"
)
func init() {
_seq.FinalizeRef = func(ref *_seq.Ref) {
refnum := ref.Bind_Num
if refnum < 0 {
panic(fmt.Sprintf("not a foreign ref: %d", refnum))
}
C.go_seq_dec_ref(C.int32_t(refnum))
}
_seq.IncForeignRef = func(refnum int32) {
if refnum < 0 {
panic(fmt.Sprintf("not a foreign ref: %d", refnum))
}
C.go_seq_inc_ref(C.int32_t(refnum))
}
// Workaround for issue #17393.
signal.Notify(make(chan os.Signal), syscall.SIGPIPE)
}
// IncGoRef is called by foreign code to pin a Go object while its refnum is crossing
// the language barrier
//export IncGoRef
func IncGoRef(refnum C.int32_t) {
_seq.Inc(int32(refnum))
}
func main() {}

153
bind/seq/ref.go Normal file
View file

@ -0,0 +1,153 @@
// Copyright 2014 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 seq
//#cgo LDFLAGS: -llog
//#include <android/log.h>
//#include <string.h>
//import "C"
import (
"fmt"
"runtime"
"sync"
)
type countedObj struct {
obj interface{}
cnt int32
}
// also known to bind/java/Seq.java and bind/objc/seq_darwin.m
const NullRefNum = 41
// refs stores Go objects that have been passed to another language.
var refs struct {
sync.Mutex
next int32 // next reference number to use for Go object, always negative
refs map[interface{}]int32
objs map[int32]countedObj
}
func init() {
refs.Lock()
refs.next = -24 // Go objects get negative reference numbers. Arbitrary starting point.
refs.refs = make(map[interface{}]int32)
refs.objs = make(map[int32]countedObj)
refs.Unlock()
}
// A Ref represents a Java or Go object passed across the language
// boundary.
type Ref struct {
Bind_Num int32
}
type proxy interface {
// Use a strange name and hope that user code does not implement it
Bind_proxy_refnum__() int32
}
// ToRefNum increments the reference count for an object and
// returns its refnum.
func ToRefNum(obj interface{}) int32 {
// We don't track foreign objects, so if obj is a proxy
// return its refnum.
if r, ok := obj.(proxy); ok {
refnum := r.Bind_proxy_refnum__()
if refnum <= 0 {
panic(fmt.Errorf("seq: proxy contained invalid Go refnum: %d", refnum))
}
return refnum
}
refs.Lock()
num := refs.refs[obj]
if num != 0 {
s := refs.objs[num]
refs.objs[num] = countedObj{s.obj, s.cnt + 1}
} else {
num = refs.next
refs.next--
if refs.next > 0 {
panic("refs.next underflow")
}
refs.refs[obj] = num
refs.objs[num] = countedObj{obj, 1}
}
refs.Unlock()
return num
}
// FromRefNum returns the Ref for a refnum. If the refnum specifies a
// foreign object, a finalizer is set to track its lifetime.
func FromRefNum(num int32) *Ref {
if num == NullRefNum {
return nil
}
ref := &Ref{num}
if num > 0 {
// This is a foreign object reference.
// Track its lifetime with a finalizer.
runtime.SetFinalizer(ref, FinalizeRef)
}
return ref
}
// Bind_IncNum increments the foreign reference count and
// return the refnum.
func (r *Ref) Bind_IncNum() int32 {
refnum := r.Bind_Num
IncForeignRef(refnum)
// Make sure this reference is not finalized before
// the foreign reference count is incremented.
runtime.KeepAlive(r)
return refnum
}
// Get returns the underlying object.
func (r *Ref) Get() interface{} {
refnum := r.Bind_Num
refs.Lock()
o, ok := refs.objs[refnum]
refs.Unlock()
if !ok {
panic(fmt.Sprintf("unknown ref %d", refnum))
}
// This is a Go reference and its refnum was incremented
// before crossing the language barrier.
Delete(refnum)
return o.obj
}
// Inc increments the reference count for a refnum. Called from Bind_proxy_refnum
// functions.
func Inc(num int32) {
refs.Lock()
o, ok := refs.objs[num]
if !ok {
panic(fmt.Sprintf("seq.Inc: unknown refnum: %d", num))
}
refs.objs[num] = countedObj{o.obj, o.cnt + 1}
refs.Unlock()
}
// Delete decrements the reference count and removes the pinned object
// from the object map when the reference count becomes zero.
func Delete(num int32) {
refs.Lock()
defer refs.Unlock()
o, ok := refs.objs[num]
if !ok {
panic(fmt.Sprintf("seq.Delete unknown refnum: %d", num))
}
if o.cnt <= 1 {
delete(refs.objs, num)
delete(refs.refs, o.obj)
} else {
refs.objs[num] = countedObj{o.obj, o.cnt - 1}
}
}

21
bind/seq/seq.go Normal file
View file

@ -0,0 +1,21 @@
// Copyright 2014 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 seq implements the machine-dependent seq serialization format.
//
// Implementations of Transact and FinalizeRef are provided by a
// specific foreign language binding package, e.g. go.mobile/bind/java.
//
// Designed only for use by the code generated by gobind. Don't try to
// use this directly.
package seq
import _ "golang.org/x/mobile/internal/mobileinit"
// FinalizeRef is the finalizer used on foreign objects.
var FinalizeRef func(ref *Ref)
// IncRef increments the foreign reference count for ref while it is in transit.
// The count is decremented after the ref is received and translated on the foreign side.
var IncForeignRef func(refnum int32)

49
bind/seq/string.go Normal file
View file

@ -0,0 +1,49 @@
// Copyright 2014 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 seq
import "unicode/utf16"
// Based heavily on package unicode/utf16 from the Go standard library.
const (
replacementChar = '\uFFFD' // Unicode replacement character
maxRune = '\U0010FFFF' // Maximum valid Unicode code point.
)
const (
// 0xd800-0xdc00 encodes the high 10 bits of a pair.
// 0xdc00-0xe000 encodes the low 10 bits of a pair.
// the value is those 20 bits plus 0x10000.
surr1 = 0xd800
surr2 = 0xdc00
surr3 = 0xe000
surrSelf = 0x10000
)
// UTF16Encode utf16 encodes s into chars. It returns the resulting
// length in units of uint16. It is assumed that the chars slice
// has enough room for the encoded string.
func UTF16Encode(s string, chars []uint16) int {
n := 0
for _, v := range s {
switch {
case v < 0, surr1 <= v && v < surr3, v > maxRune:
v = replacementChar
fallthrough
case v < surrSelf:
chars[n] = uint16(v)
n += 1
default:
// surrogate pair, two uint16 values
r1, r2 := utf16.EncodeRune(v)
chars[n] = uint16(r1)
chars[n+1] = uint16(r2)
n += 2
}
}
return n
}

28
bind/seq/string_test.go Normal file
View file

@ -0,0 +1,28 @@
// Copyright 2014 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 seq
import (
"testing"
"unicode/utf16"
)
var strData = []string{
"abcxyz09{}",
"Hello, 世界",
string([]rune{0xffff, 0x10000, 0x10001, 0x12345, 0x10ffff}),
}
func TestString(t *testing.T) {
for _, test := range strData {
chars := make([]uint16, 4*len(test))
nchars := UTF16Encode(test, chars)
chars = chars[:nchars]
got := string(utf16.Decode(chars))
if got != test {
t.Errorf("UTF16: got %q, want %q", got, test)
}
}
}

25
bind/testdata/basictypes.go vendored Normal file
View file

@ -0,0 +1,25 @@
// Copyright 2014 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 basictypes
const (
AString = "a string"
AnInt = 7
AnInt2 = 1<<63 - 1
AFloat = 0.2015
ARune = rune(32)
ABool = true
ALongString = "LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString"
)
func Ints(x int8, y int16, z int32, t int64, u int) {}
func Error() error { return nil }
func ErrorPair() (int, error) { return 0, nil }
func ByteArrays(x []byte) []byte { return nil }
func Bool(bool) bool { return true }

73
bind/testdata/basictypes.go.golden vendored Normal file
View file

@ -0,0 +1,73 @@
// Code generated by gobind. DO NOT EDIT.
// Package main is an autogenerated binder stub for package basictypes.
//
// autogenerated by gobind -lang=go basictypes
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "basictypes.h"
*/
import "C"
import (
"basictypes"
_seq "golang.org/x/mobile/bind/seq"
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
//export proxybasictypes__Bool
func proxybasictypes__Bool(param_p0 C.char) C.char {
_param_p0 := param_p0 != 0
res_0 := basictypes.Bool(_param_p0)
var _res_0 C.char = 0
if res_0 {
_res_0 = 1
}
return _res_0
}
//export proxybasictypes__ByteArrays
func proxybasictypes__ByteArrays(param_x C.nbyteslice) C.nbyteslice {
_param_x := toSlice(param_x, false)
res_0 := basictypes.ByteArrays(_param_x)
_res_0 := fromSlice(res_0, true)
return _res_0
}
//export proxybasictypes__Error
func proxybasictypes__Error() C.int32_t {
res_0 := basictypes.Error()
var _res_0 C.int32_t = _seq.NullRefNum
if res_0 != nil {
_res_0 = C.int32_t(_seq.ToRefNum(res_0))
}
return _res_0
}
//export proxybasictypes__ErrorPair
func proxybasictypes__ErrorPair() (C.nint, C.int32_t) {
res_0, res_1 := basictypes.ErrorPair()
_res_0 := C.nint(res_0)
var _res_1 C.int32_t = _seq.NullRefNum
if res_1 != nil {
_res_1 = C.int32_t(_seq.ToRefNum(res_1))
}
return _res_0, _res_1
}
//export proxybasictypes__Ints
func proxybasictypes__Ints(param_x C.int8_t, param_y C.int16_t, param_z C.int32_t, param_t C.int64_t, param_u C.nint) {
_param_x := int8(param_x)
_param_y := int16(param_y)
_param_z := int32(param_z)
_param_t := int64(param_t)
_param_u := int(param_u)
basictypes.Ints(_param_x, _param_y, _param_z, _param_t, _param_u)
}

61
bind/testdata/basictypes.java.c.golden vendored Normal file
View file

@ -0,0 +1,61 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java basictypes
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "basictypes.h"
JNIEXPORT void JNICALL
Java_basictypes_Basictypes__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
}
JNIEXPORT jboolean JNICALL
Java_basictypes_Basictypes_bool(JNIEnv* env, jclass _clazz, jboolean p0) {
char _p0 = (char)p0;
char r0 = proxybasictypes__Bool(_p0);
jboolean _r0 = r0 ? JNI_TRUE : JNI_FALSE;
return _r0;
}
JNIEXPORT jbyteArray JNICALL
Java_basictypes_Basictypes_byteArrays(JNIEnv* env, jclass _clazz, jbyteArray x) {
nbyteslice _x = go_seq_from_java_bytearray(env, x, 0);
nbyteslice r0 = proxybasictypes__ByteArrays(_x);
go_seq_release_byte_array(env, x, _x.ptr);
jbyteArray _r0 = go_seq_to_java_bytearray(env, r0, 1);
return _r0;
}
JNIEXPORT void JNICALL
Java_basictypes_Basictypes_error(JNIEnv* env, jclass _clazz) {
int32_t r0 = proxybasictypes__Error();
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r0);
}
JNIEXPORT jlong JNICALL
Java_basictypes_Basictypes_errorPair(JNIEnv* env, jclass _clazz) {
struct proxybasictypes__ErrorPair_return res = proxybasictypes__ErrorPair();
jlong _r0 = (jlong)res.r0;
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r1);
return _r0;
}
JNIEXPORT void JNICALL
Java_basictypes_Basictypes_ints(JNIEnv* env, jclass _clazz, jbyte x, jshort y, jint z, jlong t, jlong u) {
int8_t _x = (int8_t)x;
int16_t _y = (int16_t)y;
int32_t _z = (int32_t)z;
int64_t _t = (int64_t)t;
nint _u = (nint)u;
proxybasictypes__Ints(_x, _y, _z, _t, _u);
}

37
bind/testdata/basictypes.java.golden vendored Normal file
View file

@ -0,0 +1,37 @@
// Code generated by gobind. DO NOT EDIT.
// Java class basictypes.Basictypes is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java basictypes
package basictypes;
import go.Seq;
public abstract class Basictypes {
static {
Seq.touch(); // for loading the native library
_init();
}
private Basictypes() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
public static final boolean ABool = true;
public static final double AFloat = 0.2015;
public static final String ALongString = "LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString";
public static final int ARune = 32;
public static final String AString = "a string";
public static final long AnInt = 7L;
public static final long AnInt2 = 9223372036854775807L;
public static native boolean bool(boolean p0);
public static native byte[] byteArrays(byte[] x);
public static native void error() throws Exception;
public static native long errorPair() throws Exception;
public static native void ints(byte x, short y, int z, long t, long u);
}

12
bind/testdata/basictypes.java.h.golden vendored Normal file
View file

@ -0,0 +1,12 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java basictypes
#ifndef __Basictypes_H__
#define __Basictypes_H__
#include <jni.h>
#endif

View file

@ -0,0 +1,11 @@
// Objective-C API for talking to basictypes Go package.
// gobind -lang=objc basictypes
//
// File is generated by gobind. Do not edit.
#ifndef __GO_basictypes_H__
#define __GO_basictypes_H__
#include <stdint.h>
#include <objc/objc.h>
#endif

32
bind/testdata/basictypes.objc.h.golden vendored Normal file
View file

@ -0,0 +1,32 @@
// Objective-C API for talking to basictypes Go package.
// gobind -lang=objc basictypes
//
// File is generated by gobind. Do not edit.
#ifndef __Basictypes_H__
#define __Basictypes_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
FOUNDATION_EXPORT const BOOL BasictypesABool;
FOUNDATION_EXPORT const double BasictypesAFloat;
FOUNDATION_EXPORT NSString* _Nonnull const BasictypesALongString;
FOUNDATION_EXPORT const int32_t BasictypesARune;
FOUNDATION_EXPORT NSString* _Nonnull const BasictypesAString;
FOUNDATION_EXPORT const int64_t BasictypesAnInt;
FOUNDATION_EXPORT const int64_t BasictypesAnInt2;
FOUNDATION_EXPORT BOOL BasictypesBool(BOOL p0);
FOUNDATION_EXPORT NSData* _Nullable BasictypesByteArrays(NSData* _Nullable x);
FOUNDATION_EXPORT BOOL BasictypesError(NSError* _Nullable* _Nullable error);
FOUNDATION_EXPORT BOOL BasictypesErrorPair(long* _Nullable ret0_, NSError* _Nullable* _Nullable error);
FOUNDATION_EXPORT void BasictypesInts(int8_t x, int16_t y, int32_t z, int64_t t, long u);
#endif

82
bind/testdata/basictypes.objc.m.golden vendored Normal file
View file

@ -0,0 +1,82 @@
// Objective-C API for talking to basictypes Go package.
// gobind -lang=objc basictypes
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "Basictypes.objc.h"
const BOOL BasictypesABool = YES;
const double BasictypesAFloat = 0.2015;
NSString* const BasictypesALongString = @"LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString,LongString";
const int32_t BasictypesARune = 32;
NSString* const BasictypesAString = @"a string";
const int64_t BasictypesAnInt = 7LL;
const int64_t BasictypesAnInt2 = 9223372036854775807LL;
BOOL BasictypesBool(BOOL p0) {
char _p0 = (char)p0;
char r0 = proxybasictypes__Bool(_p0);
BOOL _ret0_ = r0 ? YES : NO;
return _ret0_;
}
NSData* _Nullable BasictypesByteArrays(NSData* _Nullable x) {
nbyteslice _x = go_seq_from_objc_bytearray(x, 0);
nbyteslice r0 = proxybasictypes__ByteArrays(_x);
if (![x isKindOfClass:[NSMutableData class]]) {
free(_x.ptr);
}
NSData *_ret0_ = go_seq_to_objc_bytearray(r0, 1);
return _ret0_;
}
BOOL BasictypesError(NSError* _Nullable* _Nullable error) {
int32_t r0 = proxybasictypes__Error();
Universeerror* _error = nil;
GoSeqRef* _error_ref = go_seq_from_refnum(r0);
if (_error_ref != NULL) {
_error = _error_ref.obj;
if (_error == nil) {
_error = [[Universeerror alloc] initWithRef:_error_ref];
}
}
if (_error != nil && error != nil) {
*error = _error;
}
return (_error == nil);
}
BOOL BasictypesErrorPair(long* _Nullable ret0_, NSError* _Nullable* _Nullable error) {
struct proxybasictypes__ErrorPair_return res = proxybasictypes__ErrorPair();
long _ret0_ = (long)res.r0;
Universeerror* _error = nil;
GoSeqRef* _error_ref = go_seq_from_refnum(res.r1);
if (_error_ref != NULL) {
_error = _error_ref.obj;
if (_error == nil) {
_error = [[Universeerror alloc] initWithRef:_error_ref];
}
}
*ret0_ = _ret0_;
if (_error != nil && error != nil) {
*error = _error;
}
return (_error == nil);
}
void BasictypesInts(int8_t x, int16_t y, int32_t z, int64_t t, long u) {
int8_t _x = (int8_t)x;
int16_t _y = (int16_t)y;
int32_t _z = (int32_t)z;
int64_t _t = (int64_t)t;
nint _u = (nint)u;
proxybasictypes__Ints(_x, _y, _z, _t, _u);
}
__attribute__((constructor)) static void init() {
init_seq();
}

171
bind/testdata/benchmark/benchmark.go vendored Normal file
View file

@ -0,0 +1,171 @@
// 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 benchmark contains benchmarking bound functions for internal use.
package benchmark
import (
"log"
"time"
)
type Benchmarks interface {
// It seems to be much faster to call a native function from Java
// when there is already a native call earlier in the stack.
// Run runs a named benchmark from a different thread, with
// no native call prior in the stack.
Run(name string, n int)
// RunDirect runs a named benchmark directly, with the native
// context from the call itself.
RunDirect(name string, n int)
// Callbacks for Go benchmarks
NewI() I
Noargs()
Onearg(_ int)
Oneret() int
Ref(_ I)
Manyargs(_, _, _, _, _, _, _, _, _, _ int)
String(_ string)
StringRetShort() string
StringRetLong() string
Slice(_ []byte)
}
type (
I interface {
F()
}
AnI struct {
}
)
func (_ *AnI) F() {
}
func NewI() I {
return new(AnI)
}
func runBenchmark(name string, f func(n int)) {
// Run once for warmup
f(1)
n := 1000
var dt time.Duration
minDuration := 1 * time.Second
for dt < minDuration {
n *= 2
t0 := time.Now()
f(n)
dt = time.Since(t0)
}
log.Printf("Benchmark%s %d %d ns/op\n", name, n, dt.Nanoseconds()/int64(n))
}
func runGoBenchmark(name string, f func()) {
runBenchmark("Go"+name, func(n int) {
for i := 0; i < n; i++ {
f()
}
})
runBenchmark("Go"+name+"Direct", func(n int) {
done := make(chan struct{})
go func() {
for i := 0; i < n; i++ {
f()
}
close(done)
}()
<-done
})
}
func RunBenchmarks(b Benchmarks) {
names := []string{
"Empty",
"Noargs",
"Onearg",
"Oneret",
"Manyargs",
"Refforeign",
"Refgo",
"StringShort",
"StringLong",
"StringShortUnicode",
"StringLongUnicode",
"StringRetShort",
"StringRetLong",
"SliceShort",
"SliceLong",
}
for _, name := range names {
runBenchmark("Foreign"+name, func(n int) {
b.Run(name, n)
})
runBenchmark("Foreign"+name+"Direct", func(n int) {
b.RunDirect(name, n)
})
}
runGoBenchmark("Empty", func() {})
runGoBenchmark("Noarg", func() { b.Noargs() })
runGoBenchmark("Onearg", func() { b.Onearg(0) })
runGoBenchmark("Oneret", func() { b.Oneret() })
foreignRef := b.NewI()
runGoBenchmark("Refforeign", func() { b.Ref(foreignRef) })
goRef := NewI()
runGoBenchmark("Refgo", func() { b.Ref(goRef) })
runGoBenchmark("Manyargs", func() { b.Manyargs(0, 0, 0, 0, 0, 0, 0, 0, 0, 0) })
runGoBenchmark("StringShort", func() { b.String(ShortString) })
runGoBenchmark("StringLong", func() { b.String(LongString) })
runGoBenchmark("StringShortUnicode", func() { b.String(ShortStringUnicode) })
runGoBenchmark("StringLongUnicode", func() { b.String(LongStringUnicode) })
runGoBenchmark("StringRetShort", func() { b.StringRetShort() })
runGoBenchmark("StringRetLong", func() { b.StringRetLong() })
runGoBenchmark("SliceShort", func() { b.Slice(ShortSlice) })
runGoBenchmark("SliceLong", func() { b.Slice(LongSlice) })
}
func Noargs() {
}
func Onearg(_ int) {
}
func Manyargs(_, _, _, _, _, _, _, _, _, _ int) {
}
func Oneret() int {
return 0
}
func String(_ string) {
}
func StringRetShort() string {
return ShortString
}
func StringRetLong() string {
return LongString
}
func Slice(_ []byte) {
}
func Ref(_ I) {
}
var (
ShortSlice = make([]byte, 10)
LongSlice = make([]byte, 100000)
)
const (
ShortString = "Hello, World!"
LongString = "Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!, World!"
ShortStringUnicode = "Hello, 世界!"
LongStringUnicode = "Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界! Hello, 世界!, 世界!"
)

9
bind/testdata/cgopkg/cgopkg.go vendored Normal file
View file

@ -0,0 +1,9 @@
package cgopkg
import "C"
import (
_ "golang.org/x/mobile/gl"
)
func Dummy() {}

62
bind/testdata/classes.go vendored Normal file
View file

@ -0,0 +1,62 @@
// Copyright 2014 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 java
import (
gopkg "Java/java"
"Java/java/io"
"Java/java/lang"
"Java/java/lang/System"
"Java/java/util/Spliterators"
"Java/java/util/concurrent"
)
type Runnable struct {
lang.Runnable
}
func (r *Runnable) Run(this gopkg.Runnable) {
}
type InputStream struct {
io.InputStream
}
func (_ *InputStream) Read() (int32, error) {
return 0, nil
}
func NewInputStream() *InputStream {
return new(InputStream)
}
type Future struct {
concurrent.Future
}
func (_ *Future) Get() (lang.Object, error) {
return nil, nil
}
// Use a trailing underscore to override multiple overloaded methods.
func (_ *Future) Get_(_ int64, _ concurrent.TimeUnit) (lang.Object, error) {
return nil, nil
}
type Object struct {
lang.Object
}
func innerClassTypes() {
// java.util.Spliterators.iterator use inner class types
// for the return value as well as parameters.
Spliterators.Iterator(nil)
}
func returnType() {
// Implicit types (java.io.Console) should be wrapped.
cons := System.Console()
cons.Flush()
}

2136
bind/testdata/classes.go.golden vendored Normal file

File diff suppressed because it is too large Load diff

892
bind/testdata/classes.java.c.golden vendored Normal file
View file

@ -0,0 +1,892 @@
// Code generated by gobind. DO NOT EDIT.
#include <jni.h>
#include "seq.h"
#include "classes.h"
static jclass class_java_lang_Runnable;
static jmethodID m_java_lang_Runnable_run;
static jclass class_java_io_InputStream;
static jmethodID m_java_io_InputStream_read__;
static jmethodID m_java_io_InputStream_read___3B;
static jmethodID m_java_io_InputStream_read___3BII;
static jmethodID m_java_io_InputStream_toString;
static jclass class_java_util_concurrent_Future;
static jmethodID m_java_util_concurrent_Future_get__;
static jmethodID m_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2;
static jclass class_java_lang_Object;
static jmethodID m_java_lang_Object_toString;
static jclass class_java_util_concurrent_TimeUnit;
static jmethodID m_java_util_concurrent_TimeUnit_toString;
static jclass class_java_util_Spliterators;
static jmethodID m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_2;
static jmethodID m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2;
static jmethodID m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfLong_2;
static jmethodID m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfDouble_2;
static jmethodID m_java_util_Spliterators_toString;
ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_2(jint a0) {
JNIEnv *env = go_seq_push_local_frame(1);
jobject _a0 = go_seq_from_refnum(env, a0, NULL, NULL);
jobject res = (*env)->CallStaticObjectMethod(env, class_java_util_Spliterators, m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_2, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jint a0) {
JNIEnv *env = go_seq_push_local_frame(1);
jobject _a0 = go_seq_from_refnum(env, a0, NULL, NULL);
jobject res = (*env)->CallStaticObjectMethod(env, class_java_util_Spliterators, m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfLong_2(jint a0) {
JNIEnv *env = go_seq_push_local_frame(1);
jobject _a0 = go_seq_from_refnum(env, a0, NULL, NULL);
jobject res = (*env)->CallStaticObjectMethod(env, class_java_util_Spliterators, m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfLong_2, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfDouble_2(jint a0) {
JNIEnv *env = go_seq_push_local_frame(1);
jobject _a0 = go_seq_from_refnum(env, a0, NULL, NULL);
jobject res = (*env)->CallStaticObjectMethod(env, class_java_util_Spliterators, m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfDouble_2, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
static jclass class_java_lang_System;
static jmethodID m_s_java_lang_System_console;
static jmethodID m_java_lang_System_toString;
ret_jint cproxy_s_java_lang_System_console() {
JNIEnv *env = go_seq_push_local_frame(0);
jobject res = (*env)->CallStaticObjectMethod(env, class_java_lang_System, m_s_java_lang_System_console);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
static jclass class_java_Future;
static jclass sclass_java_Future;
static jmethodID m_java_Future_get__;
static jmethodID sm_java_Future_get__;
static jmethodID m_java_Future_get__JLjava_util_concurrent_TimeUnit_2;
static jmethodID sm_java_Future_get__JLjava_util_concurrent_TimeUnit_2;
static jclass class_java_InputStream;
static jclass sclass_java_InputStream;
static jmethodID m_java_InputStream_read__;
static jmethodID sm_java_InputStream_read__;
static jmethodID m_java_InputStream_read___3B;
static jmethodID sm_java_InputStream_read___3B;
static jmethodID m_java_InputStream_read___3BII;
static jmethodID sm_java_InputStream_read___3BII;
static jmethodID m_java_InputStream_toString;
static jmethodID sm_java_InputStream_toString;
static jclass class_java_Object;
static jclass sclass_java_Object;
static jmethodID m_java_Object_toString;
static jmethodID sm_java_Object_toString;
static jclass class_java_Runnable;
static jclass sclass_java_Runnable;
static jmethodID m_java_Runnable_run;
static jmethodID sm_java_Runnable_run;
static jclass class_java_util_Iterator;
static jclass class_java_util_Spliterator;
static jclass class_java_util_PrimitiveIterator_OfInt;
static jclass class_java_util_Spliterator_OfInt;
static jclass class_java_util_PrimitiveIterator_OfLong;
static jclass class_java_util_Spliterator_OfLong;
static jclass class_java_util_PrimitiveIterator_OfDouble;
static jclass class_java_util_Spliterator_OfDouble;
static jclass class_java_io_Console;
static jmethodID m_java_io_Console_flush;
static jmethodID m_java_io_Console_toString;
void init_proxies() {
JNIEnv *env = go_seq_push_local_frame(20);
jclass clazz;
clazz = go_seq_find_class("java/lang/Runnable");
if (clazz != NULL) {
class_java_lang_Runnable = (*env)->NewGlobalRef(env, clazz);
m_java_lang_Runnable_run = go_seq_get_method_id(clazz, "run", "()V");
}
clazz = go_seq_find_class("java/io/InputStream");
if (clazz != NULL) {
class_java_io_InputStream = (*env)->NewGlobalRef(env, clazz);
m_java_io_InputStream_read__ = go_seq_get_method_id(clazz, "read", "()I");
m_java_io_InputStream_read___3B = go_seq_get_method_id(clazz, "read", "([B)I");
m_java_io_InputStream_read___3BII = go_seq_get_method_id(clazz, "read", "([BII)I");
m_java_io_InputStream_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/util/concurrent/Future");
if (clazz != NULL) {
class_java_util_concurrent_Future = (*env)->NewGlobalRef(env, clazz);
m_java_util_concurrent_Future_get__ = go_seq_get_method_id(clazz, "get", "()Ljava/lang/Object;");
m_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2 = go_seq_get_method_id(clazz, "get", "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;");
}
clazz = go_seq_find_class("java/lang/Object");
if (clazz != NULL) {
class_java_lang_Object = (*env)->NewGlobalRef(env, clazz);
m_java_lang_Object_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/util/concurrent/TimeUnit");
if (clazz != NULL) {
class_java_util_concurrent_TimeUnit = (*env)->NewGlobalRef(env, clazz);
m_java_util_concurrent_TimeUnit_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/util/Spliterators");
if (clazz != NULL) {
class_java_util_Spliterators = (*env)->NewGlobalRef(env, clazz);
m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_2 = go_seq_get_static_method_id(clazz, "iterator", "(Ljava/util/Spliterator;)Ljava/util/Iterator;");
m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2 = go_seq_get_static_method_id(clazz, "iterator", "(Ljava/util/Spliterator$OfInt;)Ljava/util/PrimitiveIterator$OfInt;");
m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfLong_2 = go_seq_get_static_method_id(clazz, "iterator", "(Ljava/util/Spliterator$OfLong;)Ljava/util/PrimitiveIterator$OfLong;");
m_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfDouble_2 = go_seq_get_static_method_id(clazz, "iterator", "(Ljava/util/Spliterator$OfDouble;)Ljava/util/PrimitiveIterator$OfDouble;");
m_java_util_Spliterators_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/lang/System");
if (clazz != NULL) {
class_java_lang_System = (*env)->NewGlobalRef(env, clazz);
m_s_java_lang_System_console = go_seq_get_static_method_id(clazz, "console", "()Ljava/io/Console;");
m_java_lang_System_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/Future");
if (clazz != NULL) {
class_java_Future = (*env)->NewGlobalRef(env, clazz);
sclass_java_Future = (*env)->GetSuperclass(env, clazz);
sclass_java_Future = (*env)->NewGlobalRef(env, sclass_java_Future);
m_java_Future_get__ = go_seq_get_method_id(clazz, "get", "()Ljava/lang/Object;");
sm_java_Future_get__ = go_seq_get_method_id(sclass_java_Future, "get", "()Ljava/lang/Object;");
m_java_Future_get__JLjava_util_concurrent_TimeUnit_2 = go_seq_get_method_id(clazz, "get", "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;");
sm_java_Future_get__JLjava_util_concurrent_TimeUnit_2 = go_seq_get_method_id(sclass_java_Future, "get", "(JLjava/util/concurrent/TimeUnit;)Ljava/lang/Object;");
}
clazz = go_seq_find_class("java/InputStream");
if (clazz != NULL) {
class_java_InputStream = (*env)->NewGlobalRef(env, clazz);
sclass_java_InputStream = (*env)->GetSuperclass(env, clazz);
sclass_java_InputStream = (*env)->NewGlobalRef(env, sclass_java_InputStream);
m_java_InputStream_read__ = go_seq_get_method_id(clazz, "read", "()I");
sm_java_InputStream_read__ = go_seq_get_method_id(sclass_java_InputStream, "read", "()I");
m_java_InputStream_read___3B = go_seq_get_method_id(clazz, "read", "([B)I");
sm_java_InputStream_read___3B = go_seq_get_method_id(sclass_java_InputStream, "read", "([B)I");
m_java_InputStream_read___3BII = go_seq_get_method_id(clazz, "read", "([BII)I");
sm_java_InputStream_read___3BII = go_seq_get_method_id(sclass_java_InputStream, "read", "([BII)I");
m_java_InputStream_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
sm_java_InputStream_toString = go_seq_get_method_id(sclass_java_InputStream, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/Object");
if (clazz != NULL) {
class_java_Object = (*env)->NewGlobalRef(env, clazz);
sclass_java_Object = (*env)->GetSuperclass(env, clazz);
sclass_java_Object = (*env)->NewGlobalRef(env, sclass_java_Object);
m_java_Object_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
sm_java_Object_toString = go_seq_get_method_id(sclass_java_Object, "toString", "()Ljava/lang/String;");
}
clazz = go_seq_find_class("java/Runnable");
if (clazz != NULL) {
class_java_Runnable = (*env)->NewGlobalRef(env, clazz);
sclass_java_Runnable = (*env)->GetSuperclass(env, clazz);
sclass_java_Runnable = (*env)->NewGlobalRef(env, sclass_java_Runnable);
m_java_Runnable_run = go_seq_get_method_id(clazz, "run", "()V");
sm_java_Runnable_run = go_seq_get_method_id(sclass_java_Runnable, "run", "()V");
}
clazz = go_seq_find_class("java/util/Iterator");
if (clazz != NULL) {
class_java_util_Iterator = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/Spliterator");
if (clazz != NULL) {
class_java_util_Spliterator = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/PrimitiveIterator$OfInt");
if (clazz != NULL) {
class_java_util_PrimitiveIterator_OfInt = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/Spliterator$OfInt");
if (clazz != NULL) {
class_java_util_Spliterator_OfInt = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/PrimitiveIterator$OfLong");
if (clazz != NULL) {
class_java_util_PrimitiveIterator_OfLong = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/Spliterator$OfLong");
if (clazz != NULL) {
class_java_util_Spliterator_OfLong = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/PrimitiveIterator$OfDouble");
if (clazz != NULL) {
class_java_util_PrimitiveIterator_OfDouble = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/util/Spliterator$OfDouble");
if (clazz != NULL) {
class_java_util_Spliterator_OfDouble = (*env)->NewGlobalRef(env, clazz);
}
clazz = go_seq_find_class("java/io/Console");
if (clazz != NULL) {
class_java_io_Console = (*env)->NewGlobalRef(env, clazz);
m_java_io_Console_flush = go_seq_get_method_id(clazz, "flush", "()V");
m_java_io_Console_toString = go_seq_get_method_id(clazz, "toString", "()Ljava/lang/String;");
}
go_seq_pop_local_frame(env);
}
jint cproxy_java_lang_Runnable_run(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
(*env)->CallVoidMethod(env, _this, m_java_lang_Runnable_run);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
go_seq_pop_local_frame(env);
return _exc_ref;
}
ret_jint cproxy_java_io_InputStream_read__(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jint res = (*env)->CallIntMethod(env, _this, m_java_io_InputStream_read__);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_io_InputStream_read___3B(jint this, nbyteslice a0) {
JNIEnv *env = go_seq_push_local_frame(2);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jbyteArray _a0 = go_seq_to_java_bytearray(env, a0, 0);
jint res = (*env)->CallIntMethod(env, _this, m_java_io_InputStream_read___3B, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_io_InputStream_read___3BII(jint this, nbyteslice a0, jint a1, jint a2) {
JNIEnv *env = go_seq_push_local_frame(4);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jbyteArray _a0 = go_seq_to_java_bytearray(env, a0, 0);
jint _a1 = a1;
jint _a2 = a2;
jint res = (*env)->CallIntMethod(env, _this, m_java_io_InputStream_read___3BII, _a0, _a1, _a2);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_io_InputStream_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_io_InputStream_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_util_concurrent_Future_get__(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jobject res = (*env)->CallObjectMethod(env, _this, m_java_util_concurrent_Future_get__);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1) {
JNIEnv *env = go_seq_push_local_frame(3);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jlong _a0 = a0;
jobject _a1 = go_seq_from_refnum(env, a1, NULL, NULL);
jobject res = (*env)->CallObjectMethod(env, _this, m_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2, _a0, _a1);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_lang_Object_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_lang_Object_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_util_concurrent_TimeUnit_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_util_concurrent_TimeUnit_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_util_Spliterators_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_util_Spliterators_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_lang_System_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_lang_System_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_Future_get__(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jobject res = (*env)->CallObjectMethod(env, _this, m_java_Future_get__);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint csuper_java_Future_get__(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jobject res = (*env)->CallNonvirtualObjectMethod(env, _this, sclass_java_Future, sm_java_Future_get__);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1) {
JNIEnv *env = go_seq_push_local_frame(3);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jlong _a0 = a0;
jobject _a1 = go_seq_from_refnum(env, a1, NULL, NULL);
jobject res = (*env)->CallObjectMethod(env, _this, m_java_Future_get__JLjava_util_concurrent_TimeUnit_2, _a0, _a1);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint csuper_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1) {
JNIEnv *env = go_seq_push_local_frame(3);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jlong _a0 = a0;
jobject _a1 = go_seq_from_refnum(env, a1, NULL, NULL);
jobject res = (*env)->CallNonvirtualObjectMethod(env, _this, sclass_java_Future, sm_java_Future_get__JLjava_util_concurrent_TimeUnit_2, _a0, _a1);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
jint _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_InputStream_read__(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jint res = (*env)->CallIntMethod(env, _this, m_java_InputStream_read__);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint csuper_java_InputStream_read__(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jint res = (*env)->CallNonvirtualIntMethod(env, _this, sclass_java_InputStream, sm_java_InputStream_read__);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_InputStream_read___3B(jint this, nbyteslice a0) {
JNIEnv *env = go_seq_push_local_frame(2);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jbyteArray _a0 = go_seq_to_java_bytearray(env, a0, 0);
jint res = (*env)->CallIntMethod(env, _this, m_java_InputStream_read___3B, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint csuper_java_InputStream_read___3B(jint this, nbyteslice a0) {
JNIEnv *env = go_seq_push_local_frame(2);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jbyteArray _a0 = go_seq_to_java_bytearray(env, a0, 0);
jint res = (*env)->CallNonvirtualIntMethod(env, _this, sclass_java_InputStream, sm_java_InputStream_read___3B, _a0);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint cproxy_java_InputStream_read___3BII(jint this, nbyteslice a0, jint a1, jint a2) {
JNIEnv *env = go_seq_push_local_frame(4);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jbyteArray _a0 = go_seq_to_java_bytearray(env, a0, 0);
jint _a1 = a1;
jint _a2 = a2;
jint res = (*env)->CallIntMethod(env, _this, m_java_InputStream_read___3BII, _a0, _a1, _a2);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_jint csuper_java_InputStream_read___3BII(jint this, nbyteslice a0, jint a1, jint a2) {
JNIEnv *env = go_seq_push_local_frame(4);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jbyteArray _a0 = go_seq_to_java_bytearray(env, a0, 0);
jint _a1 = a1;
jint _a2 = a2;
jint res = (*env)->CallNonvirtualIntMethod(env, _this, sclass_java_InputStream, sm_java_InputStream_read___3BII, _a0, _a1, _a2);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = 0;
}
jint _res = res;
go_seq_pop_local_frame(env);
ret_jint __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_InputStream_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_InputStream_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_nstring csuper_java_InputStream_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallNonvirtualObjectMethod(env, _this, sclass_java_InputStream, sm_java_InputStream_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_nstring cproxy_java_Object_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_Object_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
ret_nstring csuper_java_Object_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallNonvirtualObjectMethod(env, _this, sclass_java_Object, sm_java_Object_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
jint cproxy_java_Runnable_run(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
(*env)->CallVoidMethod(env, _this, m_java_Runnable_run);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
go_seq_pop_local_frame(env);
return _exc_ref;
}
jint csuper_java_Runnable_run(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
(*env)->CallNonvirtualVoidMethod(env, _this, sclass_java_Runnable, sm_java_Runnable_run);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
go_seq_pop_local_frame(env);
return _exc_ref;
}
jint cproxy_java_io_Console_flush(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
(*env)->CallVoidMethod(env, _this, m_java_io_Console_flush);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
go_seq_pop_local_frame(env);
return _exc_ref;
}
ret_nstring cproxy_java_io_Console_toString(jint this) {
JNIEnv *env = go_seq_push_local_frame(1);
// Must be a Java object
jobject _this = go_seq_from_refnum(env, this, NULL, NULL);
jstring res = (*env)->CallObjectMethod(env, _this, m_java_io_Console_toString);
jobject _exc = go_seq_get_exception(env);
int32_t _exc_ref = go_seq_to_refnum(env, _exc);
if (_exc != NULL) {
res = NULL;
}
nstring _res = go_seq_from_java_string(env, res);
go_seq_pop_local_frame(env);
ret_nstring __res = {_res, _exc_ref};
return __res;
}
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java classes
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "java.h"
jclass proxy_class_java_Future;
jmethodID proxy_class_java_Future_cons;
jclass proxy_class_java_InputStream;
jmethodID proxy_class_java_InputStream_cons;
jclass proxy_class_java_Object;
jmethodID proxy_class_java_Object_cons;
jclass proxy_class_java_Runnable;
jmethodID proxy_class_java_Runnable_cons;
JNIEXPORT void JNICALL
Java_java_Java__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
clazz = (*env)->FindClass(env, "java/Future");
proxy_class_java_Future = (*env)->NewGlobalRef(env, clazz);
proxy_class_java_Future_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "java/Object");
proxy_class_java_Object = (*env)->NewGlobalRef(env, clazz);
proxy_class_java_Object_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "java/Runnable");
proxy_class_java_Runnable = (*env)->NewGlobalRef(env, clazz);
proxy_class_java_Runnable_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
}
JNIEXPORT jobject JNICALL
Java_java_Java_newInputStream(JNIEnv* env, jclass _clazz) {
int32_t r0 = proxyjava__NewInputStream();
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class_java_InputStream, proxy_class_java_InputStream_cons);
return _r0;
}
JNIEXPORT jint JNICALL
Java_java_Future__1_1New(JNIEnv *env, jclass clazz) {
return new_java_Future();
}
JNIEXPORT jobject JNICALL
Java_java_Future_get__(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
struct proxyjava_Future_Get_return res = proxyjava_Future_Get(o);
jobject _r0 = go_seq_from_refnum(env, res.r0, NULL, NULL);
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r1);
return _r0;
}
JNIEXPORT jobject JNICALL
Java_java_Future_get__JLjava_util_concurrent_TimeUnit_2(JNIEnv* env, jobject __this__, jlong p0, jobject p1) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int64_t _p0 = (int64_t)p0;
int32_t _p1 = go_seq_to_refnum(env, p1);
struct proxyjava_Future_Get__return res = proxyjava_Future_Get_(o, _p0, _p1);
jobject _r0 = go_seq_from_refnum(env, res.r0, NULL, NULL);
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r1);
return _r0;
}
JNIEXPORT void JNICALL
Java_java_Future_setFuture(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t _v = go_seq_to_refnum(env, v);
proxyjava_Future_Future_Set(o, _v);
}
JNIEXPORT jobject JNICALL
Java_java_Future_getFuture(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t r0 = proxyjava_Future_Future_Get(o);
jobject _r0 = go_seq_from_refnum(env, r0, NULL, NULL);
return _r0;
}
JNIEXPORT jint JNICALL
Java_java_InputStream__1_1NewInputStream(JNIEnv *env, jclass clazz) {
int32_t refnum = proxyjava__NewInputStream();
return refnum;
}
JNIEXPORT jint JNICALL
Java_java_InputStream_read__(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
struct proxyjava_InputStream_Read_return res = proxyjava_InputStream_Read(o);
jint _r0 = (jint)res.r0;
jobject _r1 = go_seq_from_refnum(env, res.r1, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r1);
return _r0;
}
JNIEXPORT void JNICALL
Java_java_InputStream_setInputStream(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t _v = go_seq_to_refnum(env, v);
proxyjava_InputStream_InputStream_Set(o, _v);
}
JNIEXPORT jobject JNICALL
Java_java_InputStream_getInputStream(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t r0 = proxyjava_InputStream_InputStream_Get(o);
jobject _r0 = go_seq_from_refnum(env, r0, NULL, NULL);
return _r0;
}
JNIEXPORT jint JNICALL
Java_java_Object__1_1New(JNIEnv *env, jclass clazz) {
return new_java_Object();
}
JNIEXPORT void JNICALL
Java_java_Object_setObject(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t _v = go_seq_to_refnum(env, v);
proxyjava_Object_Object_Set(o, _v);
}
JNIEXPORT jobject JNICALL
Java_java_Object_getObject(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t r0 = proxyjava_Object_Object_Get(o);
jobject _r0 = go_seq_from_refnum(env, r0, NULL, NULL);
return _r0;
}
JNIEXPORT jint JNICALL
Java_java_Runnable__1_1New(JNIEnv *env, jclass clazz) {
return new_java_Runnable();
}
JNIEXPORT void JNICALL
Java_java_Runnable_run(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t _this_ = go_seq_to_refnum(env, __this__);
proxyjava_Runnable_Run(o, _this_);
}
JNIEXPORT void JNICALL
Java_java_Runnable_setRunnable(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t _v = go_seq_to_refnum(env, v);
proxyjava_Runnable_Runnable_Set(o, _v);
}
JNIEXPORT jobject JNICALL
Java_java_Runnable_getRunnable(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t r0 = proxyjava_Runnable_Runnable_Get(o);
jobject _r0 = go_seq_from_refnum(env, r0, NULL, NULL);
return _r0;
}

155
bind/testdata/classes.java.golden vendored Normal file
View file

@ -0,0 +1,155 @@
// Code generated by gobind. DO NOT EDIT.
// Java class java.Future is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java classes
package java;
import go.Seq;
public final class Future implements Seq.GoObject, java.util.concurrent.Future {
static { Java.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
Future(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public Future() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
public final native java.util.concurrent.Future getFuture();
public final native void setFuture(java.util.concurrent.Future v);
@Override public native java.lang.Object get() throws java.lang.InterruptedException, java.util.concurrent.ExecutionException;
/**
* Use a trailing underscore to override multiple overloaded methods.
*/
@Override public native java.lang.Object get(long p0, java.util.concurrent.TimeUnit p1) throws java.lang.InterruptedException, java.util.concurrent.ExecutionException, java.util.concurrent.TimeoutException;
}
// Code generated by gobind. DO NOT EDIT.
// Java class java.InputStream is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java classes
package java;
import go.Seq;
public final class InputStream extends java.io.InputStream implements Seq.GoObject {
static { Java.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
public InputStream() {
super();
this.refnum = __NewInputStream();
Seq.trackGoRef(refnum, this);
}
private static native int __NewInputStream();
public final native java.io.InputStream getInputStream();
public final native void setInputStream(java.io.InputStream v);
@Override public native int read() throws java.io.IOException;
}
// Code generated by gobind. DO NOT EDIT.
// Java class java.Object is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java classes
package java;
import go.Seq;
public final class Object extends java.lang.Object implements Seq.GoObject {
static { Java.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
Object(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public Object() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
public final native java.lang.Object getObject();
public final native void setObject(java.lang.Object v);
}
// Code generated by gobind. DO NOT EDIT.
// Java class java.Runnable is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java classes
package java;
import go.Seq;
public final class Runnable implements Seq.GoObject, java.lang.Runnable {
static { Java.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
Runnable(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public Runnable() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
public final native java.lang.Runnable getRunnable();
public final native void setRunnable(java.lang.Runnable v);
@Override public native void run();
}
// Code generated by gobind. DO NOT EDIT.
// Java class java.Java is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java classes
package java;
import go.Seq;
public abstract class Java {
static {
Seq.touch(); // for loading the native library
_init();
}
private Java() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
public static native InputStream newInputStream();
}

103
bind/testdata/classes.java.h.golden vendored Normal file
View file

@ -0,0 +1,103 @@
// Code generated by gobind. DO NOT EDIT.
#include <jni.h>
#include "seq.h"
extern void init_proxies();
typedef struct ret_jint {
jint res;
jint exc;
} ret_jint;
typedef struct ret_jboolean {
jboolean res;
jint exc;
} ret_jboolean;
typedef struct ret_jshort {
jshort res;
jint exc;
} ret_jshort;
typedef struct ret_jchar {
jchar res;
jint exc;
} ret_jchar;
typedef struct ret_jbyte {
jbyte res;
jint exc;
} ret_jbyte;
typedef struct ret_jlong {
jlong res;
jint exc;
} ret_jlong;
typedef struct ret_jfloat {
jfloat res;
jint exc;
} ret_jfloat;
typedef struct ret_jdouble {
jdouble res;
jint exc;
} ret_jdouble;
typedef struct ret_nstring {
nstring res;
jint exc;
} ret_nstring;
typedef struct ret_nbyteslice {
nbyteslice res;
jint exc;
} ret_nbyteslice;
extern jint cproxy_java_lang_Runnable_run(jint this);
extern ret_jint cproxy_java_io_InputStream_read__(jint this);
extern ret_jint cproxy_java_io_InputStream_read___3B(jint this, nbyteslice a0);
extern ret_jint cproxy_java_io_InputStream_read___3BII(jint this, nbyteslice a0, jint a1, jint a2);
extern ret_nstring cproxy_java_io_InputStream_toString(jint this);
extern ret_jint cproxy_java_util_concurrent_Future_get__(jint this);
extern ret_jint cproxy_java_util_concurrent_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1);
extern ret_nstring cproxy_java_lang_Object_toString(jint this);
extern ret_nstring cproxy_java_util_concurrent_TimeUnit_toString(jint this);
extern ret_nstring cproxy_java_util_Spliterators_toString(jint this);
extern ret_nstring cproxy_java_lang_System_toString(jint this);
extern ret_jint cproxy_java_Future_get__(jint this);
extern ret_jint csuper_java_Future_get__(jint this);
extern ret_jint cproxy_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1);
extern ret_jint csuper_java_Future_get__JLjava_util_concurrent_TimeUnit_2(jint this, jlong a0, jint a1);
extern ret_jint cproxy_java_InputStream_read__(jint this);
extern ret_jint csuper_java_InputStream_read__(jint this);
extern ret_jint cproxy_java_InputStream_read___3B(jint this, nbyteslice a0);
extern ret_jint csuper_java_InputStream_read___3B(jint this, nbyteslice a0);
extern ret_jint cproxy_java_InputStream_read___3BII(jint this, nbyteslice a0, jint a1, jint a2);
extern ret_jint csuper_java_InputStream_read___3BII(jint this, nbyteslice a0, jint a1, jint a2);
extern ret_nstring cproxy_java_InputStream_toString(jint this);
extern ret_nstring csuper_java_InputStream_toString(jint this);
extern ret_nstring cproxy_java_Object_toString(jint this);
extern ret_nstring csuper_java_Object_toString(jint this);
extern jint cproxy_java_Runnable_run(jint this);
extern jint csuper_java_Runnable_run(jint this);
extern jint cproxy_java_io_Console_flush(jint this);
extern ret_nstring cproxy_java_io_Console_toString(jint this);
extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_2(jint a0);
extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfInt_2(jint a0);
extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfLong_2(jint a0);
extern ret_jint cproxy_s_java_util_Spliterators_iterator__Ljava_util_Spliterator_00024OfDouble_2(jint a0);
extern ret_jint cproxy_s_java_lang_System_console();
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java classes
#ifndef __Java_H__
#define __Java_H__
#include <jni.h>
extern jclass proxy_class_java_Future;
extern jmethodID proxy_class_java_Future_cons;
extern jclass proxy_class_java_InputStream;
extern jmethodID proxy_class_java_InputStream_cons;
extern jclass proxy_class_java_Object;
extern jmethodID proxy_class_java_Object_cons;
extern jclass proxy_class_java_Runnable;
extern jmethodID proxy_class_java_Runnable_cons;
#endif

10
bind/testdata/customprefix.go vendored Normal file
View file

@ -0,0 +1,10 @@
// Copyright 2015 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.
// Data for -pkgpath and -prefix options.
package customprefix
func F() {
}

View file

@ -0,0 +1,23 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java -javapkg=com.example customprefix
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "customprefix.h"
JNIEXPORT void JNICALL
Java_com_example_customprefix_Customprefix__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
}
JNIEXPORT void JNICALL
Java_com_example_customprefix_Customprefix_f(JNIEnv* env, jclass _clazz) {
proxycustomprefix__F();
}

26
bind/testdata/customprefix.java.golden vendored Normal file
View file

@ -0,0 +1,26 @@
// Code generated by gobind. DO NOT EDIT.
// Java class com.example.customprefix.Customprefix is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java -javapkg=com.example customprefix
package com.example.customprefix;
import go.Seq;
public abstract class Customprefix {
static {
Seq.touch(); // for loading the native library
_init();
}
private Customprefix() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
public static native void f();
}

View file

@ -0,0 +1,12 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java -javapkg=com.example customprefix
#ifndef __Customprefix_H__
#define __Customprefix_H__
#include <jni.h>
#endif

View file

@ -0,0 +1,11 @@
// Objective-C API for talking to customprefix Go package.
// gobind -lang=objc customprefix
//
// File is generated by gobind. Do not edit.
#ifndef __GO_customprefix_H__
#define __GO_customprefix_H__
#include <stdint.h>
#include <objc/objc.h>
#endif

View file

@ -0,0 +1,16 @@
// Objective-C API for talking to customprefix Go package.
// gobind -lang=objc customprefix
//
// File is generated by gobind. Do not edit.
#ifndef __Customprefix_H__
#define __Customprefix_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
FOUNDATION_EXPORT void CustomprefixF(void);
#endif

View file

@ -0,0 +1,18 @@
// Objective-C API for talking to customprefix Go package.
// gobind -lang=objc customprefix
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "Customprefix.objc.h"
void CustomprefixF(void) {
proxycustomprefix__F();
}
__attribute__((constructor)) static void init() {
init_seq();
}

View file

@ -0,0 +1,11 @@
// Objective-C API for talking to customprefix Go package.
// gobind -lang=objc -prefix="EX" customprefix
//
// File is generated by gobind. Do not edit.
#ifndef __GO_customprefix_H__
#define __GO_customprefix_H__
#include <stdint.h>
#include <objc/objc.h>
#endif

View file

@ -0,0 +1,16 @@
// Objective-C API for talking to customprefix Go package.
// gobind -lang=objc -prefix="EX" customprefix
//
// File is generated by gobind. Do not edit.
#ifndef __EXCustomprefix_H__
#define __EXCustomprefix_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
FOUNDATION_EXPORT void EXCustomprefixF(void);
#endif

View file

@ -0,0 +1,18 @@
// Objective-C API for talking to customprefix Go package.
// gobind -lang=objc -prefix="EX" customprefix
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "EXCustomprefix.objc.h"
void EXCustomprefixF(void) {
proxycustomprefix__F();
}
__attribute__((constructor)) static void init() {
init_seq();
}

59
bind/testdata/doc.go vendored Normal file
View file

@ -0,0 +1,59 @@
// 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 doc tests that Go documentation is transferred
// to the generated code.
package doc
// F is a function.
func F() {}
// C is a constant.
const C = true
// V is a var.
var V string
// A group of vars.
var (
// A specific var.
Specific string
NoDocVar float64
)
// Before is a method.
func (_ *S) Before() {}
// S is a struct.
type S struct {
// SF is a field.
SF string
// blank (unexported) field.
_ string
// Anonymous field.
*S2
// Multiple fields.
F1, F2 string
}
// After is another method.
func (_ *S) After() {}
// A generic comment with <HTML>.
type (
// S2 is a struct.
S2 struct{}
NoDoc struct{}
)
// NewS is a constructor.
func NewS() *S {
return nil
}
// I is an interface.
type I interface {
// IM is a method.
IM()
}

190
bind/testdata/doc.go.golden vendored Normal file
View file

@ -0,0 +1,190 @@
// Code generated by gobind. DO NOT EDIT.
// Package main is an autogenerated binder stub for package doc.
//
// autogenerated by gobind -lang=go doc
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "doc.h"
*/
import "C"
import (
"doc"
_seq "golang.org/x/mobile/bind/seq"
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
//export new_doc_NoDoc
func new_doc_NoDoc() C.int32_t {
return C.int32_t(_seq.ToRefNum(new(doc.NoDoc)))
}
//export proxydoc_S_SF_Set
func proxydoc_S_SF_Set(refnum C.int32_t, v C.nstring) {
ref := _seq.FromRefNum(int32(refnum))
_v := decodeString(v)
ref.Get().(*doc.S).SF = _v
}
//export proxydoc_S_SF_Get
func proxydoc_S_SF_Get(refnum C.int32_t) C.nstring {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*doc.S).SF
_v := encodeString(v)
return _v
}
//export proxydoc_S_S2_Set
func proxydoc_S_S2_Set(refnum C.int32_t, v C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
// Must be a Go object
var _v *doc.S2
if _v_ref := _seq.FromRefNum(int32(v)); _v_ref != nil {
_v = _v_ref.Get().(*doc.S2)
}
ref.Get().(*doc.S).S2 = _v
}
//export proxydoc_S_S2_Get
func proxydoc_S_S2_Get(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*doc.S).S2
var _v C.int32_t = _seq.NullRefNum
if v != nil {
_v = C.int32_t(_seq.ToRefNum(v))
}
return _v
}
//export proxydoc_S_F1_Set
func proxydoc_S_F1_Set(refnum C.int32_t, v C.nstring) {
ref := _seq.FromRefNum(int32(refnum))
_v := decodeString(v)
ref.Get().(*doc.S).F1 = _v
}
//export proxydoc_S_F1_Get
func proxydoc_S_F1_Get(refnum C.int32_t) C.nstring {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*doc.S).F1
_v := encodeString(v)
return _v
}
//export proxydoc_S_F2_Set
func proxydoc_S_F2_Set(refnum C.int32_t, v C.nstring) {
ref := _seq.FromRefNum(int32(refnum))
_v := decodeString(v)
ref.Get().(*doc.S).F2 = _v
}
//export proxydoc_S_F2_Get
func proxydoc_S_F2_Get(refnum C.int32_t) C.nstring {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*doc.S).F2
_v := encodeString(v)
return _v
}
//export proxydoc_S_After
func proxydoc_S_After(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*doc.S)
v.After()
}
//export proxydoc_S_Before
func proxydoc_S_Before(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*doc.S)
v.Before()
}
//export new_doc_S
func new_doc_S() C.int32_t {
return C.int32_t(_seq.ToRefNum(new(doc.S)))
}
//export new_doc_S2
func new_doc_S2() C.int32_t {
return C.int32_t(_seq.ToRefNum(new(doc.S2)))
}
//export proxydoc_I_IM
func proxydoc_I_IM(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(doc.I)
v.IM()
}
type proxydoc_I _seq.Ref
func (p *proxydoc_I) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxydoc_I) IM() {
C.cproxydoc_I_IM(C.int32_t(p.Bind_proxy_refnum__()))
}
//export var_setdoc_NoDocVar
func var_setdoc_NoDocVar(v C.double) {
_v := float64(v)
doc.NoDocVar = _v
}
//export var_getdoc_NoDocVar
func var_getdoc_NoDocVar() C.double {
v := doc.NoDocVar
_v := C.double(v)
return _v
}
//export var_setdoc_Specific
func var_setdoc_Specific(v C.nstring) {
_v := decodeString(v)
doc.Specific = _v
}
//export var_getdoc_Specific
func var_getdoc_Specific() C.nstring {
v := doc.Specific
_v := encodeString(v)
return _v
}
//export var_setdoc_V
func var_setdoc_V(v C.nstring) {
_v := decodeString(v)
doc.V = _v
}
//export var_getdoc_V
func var_getdoc_V() C.nstring {
v := doc.V
_v := encodeString(v)
return _v
}
//export proxydoc__F
func proxydoc__F() {
doc.F()
}
//export proxydoc__NewS
func proxydoc__NewS() C.int32_t {
res_0 := doc.NewS()
var _res_0 C.int32_t = _seq.NullRefNum
if res_0 != nil {
_res_0 = C.int32_t(_seq.ToRefNum(res_0))
}
return _res_0
}

194
bind/testdata/doc.java.c.golden vendored Normal file
View file

@ -0,0 +1,194 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java doc
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "doc.h"
jclass proxy_class_doc_I;
jmethodID proxy_class_doc_I_cons;
static jmethodID mid_I_IM;
jclass proxy_class_doc_NoDoc;
jmethodID proxy_class_doc_NoDoc_cons;
jclass proxy_class_doc_S;
jmethodID proxy_class_doc_S_cons;
jclass proxy_class_doc_S2;
jmethodID proxy_class_doc_S2_cons;
JNIEXPORT void JNICALL
Java_doc_Doc__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
clazz = (*env)->FindClass(env, "doc/NoDoc");
proxy_class_doc_NoDoc = (*env)->NewGlobalRef(env, clazz);
proxy_class_doc_NoDoc_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "doc/S");
proxy_class_doc_S = (*env)->NewGlobalRef(env, clazz);
proxy_class_doc_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "doc/S2");
proxy_class_doc_S2 = (*env)->NewGlobalRef(env, clazz);
proxy_class_doc_S2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "doc/Doc$proxyI");
proxy_class_doc_I = (*env)->NewGlobalRef(env, clazz);
proxy_class_doc_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "doc/I");
mid_I_IM = (*env)->GetMethodID(env, clazz, "im", "()V");
}
JNIEXPORT void JNICALL
Java_doc_Doc_f(JNIEnv* env, jclass _clazz) {
proxydoc__F();
}
JNIEXPORT jobject JNICALL
Java_doc_Doc_newS(JNIEnv* env, jclass _clazz) {
int32_t r0 = proxydoc__NewS();
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class_doc_S, proxy_class_doc_S_cons);
return _r0;
}
JNIEXPORT jint JNICALL
Java_doc_NoDoc__1_1New(JNIEnv *env, jclass clazz) {
return new_doc_NoDoc();
}
JNIEXPORT jint JNICALL
Java_doc_S__1_1NewS(JNIEnv *env, jclass clazz) {
int32_t refnum = proxydoc__NewS();
return refnum;
}
JNIEXPORT void JNICALL
Java_doc_S_after(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxydoc_S_After(o);
}
JNIEXPORT void JNICALL
Java_doc_S_before(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxydoc_S_Before(o);
}
JNIEXPORT void JNICALL
Java_doc_S_setSF(JNIEnv *env, jobject this, jstring v) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring _v = go_seq_from_java_string(env, v);
proxydoc_S_SF_Set(o, _v);
}
JNIEXPORT jstring JNICALL
Java_doc_S_getSF(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring r0 = proxydoc_S_SF_Get(o);
jstring _r0 = go_seq_to_java_string(env, r0);
return _r0;
}
JNIEXPORT void JNICALL
Java_doc_S_setS2(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t _v = go_seq_to_refnum(env, v);
proxydoc_S_S2_Set(o, _v);
}
JNIEXPORT jobject JNICALL
Java_doc_S_getS2(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t r0 = proxydoc_S_S2_Get(o);
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class_doc_S2, proxy_class_doc_S2_cons);
return _r0;
}
JNIEXPORT void JNICALL
Java_doc_S_setF1(JNIEnv *env, jobject this, jstring v) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring _v = go_seq_from_java_string(env, v);
proxydoc_S_F1_Set(o, _v);
}
JNIEXPORT jstring JNICALL
Java_doc_S_getF1(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring r0 = proxydoc_S_F1_Get(o);
jstring _r0 = go_seq_to_java_string(env, r0);
return _r0;
}
JNIEXPORT void JNICALL
Java_doc_S_setF2(JNIEnv *env, jobject this, jstring v) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring _v = go_seq_from_java_string(env, v);
proxydoc_S_F2_Set(o, _v);
}
JNIEXPORT jstring JNICALL
Java_doc_S_getF2(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring r0 = proxydoc_S_F2_Get(o);
jstring _r0 = go_seq_to_java_string(env, r0);
return _r0;
}
JNIEXPORT jint JNICALL
Java_doc_S2__1_1New(JNIEnv *env, jclass clazz) {
return new_doc_S2();
}
JNIEXPORT void JNICALL
Java_doc_Doc_00024proxyI_im(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxydoc_I_IM(o);
}
void cproxydoc_I_IM(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_doc_I, proxy_class_doc_I_cons);
(*env)->CallVoidMethod(env, o, mid_I_IM);
go_seq_pop_local_frame(env);
}
JNIEXPORT void JNICALL
Java_doc_Doc_setNoDocVar(JNIEnv *env, jclass clazz, jdouble v) {
double _v = (double)v;
var_setdoc_NoDocVar(_v);
}
JNIEXPORT jdouble JNICALL
Java_doc_Doc_getNoDocVar(JNIEnv *env, jclass clazz) {
double r0 = var_getdoc_NoDocVar();
jdouble _r0 = (jdouble)r0;
return _r0;
}
JNIEXPORT void JNICALL
Java_doc_Doc_setSpecific(JNIEnv *env, jclass clazz, jstring v) {
nstring _v = go_seq_from_java_string(env, v);
var_setdoc_Specific(_v);
}
JNIEXPORT jstring JNICALL
Java_doc_Doc_getSpecific(JNIEnv *env, jclass clazz) {
nstring r0 = var_getdoc_Specific();
jstring _r0 = go_seq_to_java_string(env, r0);
return _r0;
}
JNIEXPORT void JNICALL
Java_doc_Doc_setV(JNIEnv *env, jclass clazz, jstring v) {
nstring _v = go_seq_from_java_string(env, v);
var_setdoc_V(_v);
}
JNIEXPORT jstring JNICALL
Java_doc_Doc_getV(JNIEnv *env, jclass clazz) {
nstring r0 = var_getdoc_V();
jstring _r0 = go_seq_to_java_string(env, r0);
return _r0;
}

324
bind/testdata/doc.java.golden vendored Normal file
View file

@ -0,0 +1,324 @@
// Code generated by gobind. DO NOT EDIT.
// Java class doc.NoDoc is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java doc
package doc;
import go.Seq;
/**
* A generic comment with &lt;HTML&gt;.
*/
public final class NoDoc implements Seq.Proxy {
static { Doc.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
NoDoc(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public NoDoc() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof NoDoc)) {
return false;
}
NoDoc that = (NoDoc)o;
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {});
}
@Override public String toString() {
StringBuilder b = new StringBuilder();
b.append("NoDoc").append("{");
return b.append("}").toString();
}
}
// Code generated by gobind. DO NOT EDIT.
// Java class doc.S is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java doc
package doc;
import go.Seq;
/**
* S is a struct.
*/
public final class S implements Seq.Proxy {
static { Doc.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
/**
* NewS is a constructor.
*/
public S() {
this.refnum = __NewS();
Seq.trackGoRef(refnum, this);
}
private static native int __NewS();
S(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
/**
* SF is a field.
*/
public final native String getSF();
/**
* SF is a field.
*/
public final native void setSF(String v);
/**
* Anonymous field.
*/
public final native S2 getS2();
/**
* Anonymous field.
*/
public final native void setS2(S2 v);
/**
* Multiple fields.
*/
public final native String getF1();
/**
* Multiple fields.
*/
public final native void setF1(String v);
/**
* Multiple fields.
*/
public final native String getF2();
/**
* Multiple fields.
*/
public final native void setF2(String v);
/**
* After is another method.
*/
public native void after();
public native void before();
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof S)) {
return false;
}
S that = (S)o;
String thisSF = getSF();
String thatSF = that.getSF();
if (thisSF == null) {
if (thatSF != null) {
return false;
}
} else if (!thisSF.equals(thatSF)) {
return false;
}
S2 thisS2 = getS2();
S2 thatS2 = that.getS2();
if (thisS2 == null) {
if (thatS2 != null) {
return false;
}
} else if (!thisS2.equals(thatS2)) {
return false;
}
String thisF1 = getF1();
String thatF1 = that.getF1();
if (thisF1 == null) {
if (thatF1 != null) {
return false;
}
} else if (!thisF1.equals(thatF1)) {
return false;
}
String thisF2 = getF2();
String thatF2 = that.getF2();
if (thisF2 == null) {
if (thatF2 != null) {
return false;
}
} else if (!thisF2.equals(thatF2)) {
return false;
}
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {getSF(), getS2(), getF1(), getF2()});
}
@Override public String toString() {
StringBuilder b = new StringBuilder();
b.append("S").append("{");
b.append("SF:").append(getSF()).append(",");
b.append("S2:").append(getS2()).append(",");
b.append("F1:").append(getF1()).append(",");
b.append("F2:").append(getF2()).append(",");
return b.append("}").toString();
}
}
// Code generated by gobind. DO NOT EDIT.
// Java class doc.S2 is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java doc
package doc;
import go.Seq;
/**
* S2 is a struct.
*/
public final class S2 implements Seq.Proxy {
static { Doc.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
S2(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public S2() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof S2)) {
return false;
}
S2 that = (S2)o;
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {});
}
@Override public String toString() {
StringBuilder b = new StringBuilder();
b.append("S2").append("{");
return b.append("}").toString();
}
}
// Code generated by gobind. DO NOT EDIT.
// Java class doc.I is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java doc
package doc;
import go.Seq;
/**
* I is an interface.
*/
public interface I {
/**
* IM is a method.
*/
public void im();
}
// Code generated by gobind. DO NOT EDIT.
// Java class doc.Doc is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java doc
package doc;
import go.Seq;
public abstract class Doc {
static {
Seq.touch(); // for loading the native library
_init();
}
private Doc() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
private static final class proxyI implements Seq.Proxy, I {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void im();
}
/**
* C is a constant.
*/
public static final boolean C = true;
/**
* A group of vars.
*/
public static native void setNoDocVar(double v);
/**
* A group of vars.
*/
public static native double getNoDocVar();
/**
* A specific var.
*/
public static native void setSpecific(String v);
/**
* A specific var.
*/
public static native String getSpecific();
/**
* V is a var.
*/
public static native void setV(String v);
/**
* V is a var.
*/
public static native String getV();
/**
* F is a function.
*/
public static native void f();
/**
* NewS is a constructor.
*/
public static native S newS();
}

23
bind/testdata/doc.java.h.golden vendored Normal file
View file

@ -0,0 +1,23 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java doc
#ifndef __Doc_H__
#define __Doc_H__
#include <jni.h>
extern jclass proxy_class_doc_I;
extern jmethodID proxy_class_doc_I_cons;
void cproxydoc_I_IM(int32_t refnum);
extern jclass proxy_class_doc_NoDoc;
extern jmethodID proxy_class_doc_NoDoc_cons;
extern jclass proxy_class_doc_S;
extern jmethodID proxy_class_doc_S_cons;
extern jclass proxy_class_doc_S2;
extern jmethodID proxy_class_doc_S2_cons;
#endif

13
bind/testdata/doc.objc.go.h.golden vendored Normal file
View file

@ -0,0 +1,13 @@
// Objective-C API for talking to doc Go package.
// gobind -lang=objc doc
//
// File is generated by gobind. Do not edit.
#ifndef __GO_doc_H__
#define __GO_doc_H__
#include <stdint.h>
#include <objc/objc.h>
void cproxydoc_I_IM(int32_t refnum);
#endif

136
bind/testdata/doc.objc.h.golden vendored Normal file
View file

@ -0,0 +1,136 @@
// Objective-C API for talking to doc Go package.
// gobind -lang=objc doc
//
// File is generated by gobind. Do not edit.
#ifndef __Doc_H__
#define __Doc_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
@class DocNoDoc;
@class DocS;
@class DocS2;
@protocol DocI;
@class DocI;
@protocol DocI <NSObject>
/**
* IM is a method.
*/
- (void)im;
@end
/**
* A generic comment with <HTML>.
*/
@interface DocNoDoc : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (nonnull instancetype)init;
@end
/**
* S is a struct.
*/
@interface DocS : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
/**
* NewS is a constructor.
*/
- (nullable instancetype)init;
/**
* SF is a field.
*/
@property (nonatomic) NSString* _Nonnull sf;
/**
* Anonymous field.
*/
@property (nonatomic) DocS2* _Nullable s2;
/**
* Multiple fields.
*/
@property (nonatomic) NSString* _Nonnull f1;
/**
* Multiple fields.
*/
@property (nonatomic) NSString* _Nonnull f2;
/**
* After is another method.
*/
- (void)after;
- (void)before;
@end
/**
* S2 is a struct.
*/
@interface DocS2 : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (nonnull instancetype)init;
@end
/**
* C is a constant.
*/
FOUNDATION_EXPORT const BOOL DocC;
@interface Doc : NSObject
/**
* A group of vars.
*/
+ (double) noDocVar;
+ (void) setNoDocVar:(double)v;
/**
* A specific var.
*/
+ (NSString* _Nonnull) specific;
+ (void) setSpecific:(NSString* _Nonnull)v;
/**
* V is a var.
*/
+ (NSString* _Nonnull) v;
+ (void) setV:(NSString* _Nonnull)v;
@end
/**
* F is a function.
*/
FOUNDATION_EXPORT void DocF(void);
/**
* NewS is a constructor.
*/
FOUNDATION_EXPORT DocS* _Nullable DocNewS(void);
@class DocI;
/**
* I is an interface.
*/
@interface DocI : NSObject <goSeqRefInterface, DocI> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
/**
* IM is a method.
*/
- (void)im;
@end
#endif

231
bind/testdata/doc.objc.m.golden vendored Normal file
View file

@ -0,0 +1,231 @@
// Objective-C API for talking to doc Go package.
// gobind -lang=objc doc
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "Doc.objc.h"
@implementation DocNoDoc {
}
- (nonnull instancetype)initWithRef:(_Nonnull id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (nonnull instancetype)init {
self = [super init];
if (self) {
__ref = go_seq_from_refnum(new_doc_NoDoc());
}
return self;
}
@end
@implementation DocS {
}
- (nonnull instancetype)initWithRef:(_Nonnull id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (instancetype)init {
self = [super init];
if (!self) return nil;
int32_t refnum = proxydoc__NewS();
__ref = go_seq_from_refnum(refnum);
return self;
}
- (NSString* _Nonnull)sf {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring r0 = proxydoc_S_SF_Get(refnum);
NSString *_r0 = go_seq_to_objc_string(r0);
return _r0;
}
- (void)setSF:(NSString* _Nonnull)v {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring _v = go_seq_from_objc_string(v);
proxydoc_S_SF_Set(refnum, _v);
}
- (DocS2* _Nullable)s2 {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxydoc_S_S2_Get(refnum);
DocS2* _r0 = nil;
GoSeqRef* _r0_ref = go_seq_from_refnum(r0);
if (_r0_ref != NULL) {
_r0 = _r0_ref.obj;
if (_r0 == nil) {
_r0 = [[DocS2 alloc] initWithRef:_r0_ref];
}
}
return _r0;
}
- (void)setS2:(DocS2* _Nullable)v {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t _v;
if ([v conformsToProtocol:@protocol(goSeqRefInterface)]) {
id<goSeqRefInterface> v_proxy = (id<goSeqRefInterface>)(v);
_v = go_seq_go_to_refnum(v_proxy._ref);
} else {
_v = go_seq_to_refnum(v);
}
proxydoc_S_S2_Set(refnum, _v);
}
- (NSString* _Nonnull)f1 {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring r0 = proxydoc_S_F1_Get(refnum);
NSString *_r0 = go_seq_to_objc_string(r0);
return _r0;
}
- (void)setF1:(NSString* _Nonnull)v {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring _v = go_seq_from_objc_string(v);
proxydoc_S_F1_Set(refnum, _v);
}
- (NSString* _Nonnull)f2 {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring r0 = proxydoc_S_F2_Get(refnum);
NSString *_r0 = go_seq_to_objc_string(r0);
return _r0;
}
- (void)setF2:(NSString* _Nonnull)v {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring _v = go_seq_from_objc_string(v);
proxydoc_S_F2_Set(refnum, _v);
}
- (void)after {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxydoc_S_After(refnum);
}
- (void)before {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxydoc_S_Before(refnum);
}
@end
@implementation DocS2 {
}
- (nonnull instancetype)initWithRef:(_Nonnull id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (nonnull instancetype)init {
self = [super init];
if (self) {
__ref = go_seq_from_refnum(new_doc_S2());
}
return self;
}
@end
@implementation DocI {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)im {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxydoc_I_IM(refnum);
}
@end
const BOOL DocC = YES;
@implementation Doc
+ (void) setNoDocVar:(double)v {
double _v = (double)v;
var_setdoc_NoDocVar(_v);
}
+ (double) noDocVar {
double r0 = var_getdoc_NoDocVar();
double _r0 = (double)r0;
return _r0;
}
+ (void) setSpecific:(NSString* _Nonnull)v {
nstring _v = go_seq_from_objc_string(v);
var_setdoc_Specific(_v);
}
+ (NSString* _Nonnull) specific {
nstring r0 = var_getdoc_Specific();
NSString *_r0 = go_seq_to_objc_string(r0);
return _r0;
}
+ (void) setV:(NSString* _Nonnull)v {
nstring _v = go_seq_from_objc_string(v);
var_setdoc_V(_v);
}
+ (NSString* _Nonnull) v {
nstring r0 = var_getdoc_V();
NSString *_r0 = go_seq_to_objc_string(r0);
return _r0;
}
@end
void DocF(void) {
proxydoc__F();
}
DocS* _Nullable DocNewS(void) {
int32_t r0 = proxydoc__NewS();
DocS* _ret0_ = nil;
GoSeqRef* _ret0__ref = go_seq_from_refnum(r0);
if (_ret0__ref != NULL) {
_ret0_ = _ret0__ref.obj;
if (_ret0_ == nil) {
_ret0_ = [[DocS alloc] initWithRef:_ret0__ref];
}
}
return _ret0_;
}
void cproxydoc_I_IM(int32_t refnum) {
@autoreleasepool {
DocI* o = go_seq_objc_from_refnum(refnum);
[o im];
}
}
__attribute__((constructor)) static void init() {
init_seq();
}

59
bind/testdata/ignore.go vendored Normal file
View file

@ -0,0 +1,59 @@
// 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 ignore tests that exported, but otherwise
// unsupported functions, variables, fields and methods
// are ignored by the generators
package ignore
var Var interface{}
type (
NamedString string
)
const NamedConst NamedString = "foo"
var V interface{}
func Argument(_ interface{}) {
}
func Result() interface{} {
return nil
}
type S struct {
F interface{}
}
type (
F func()
)
func (_ *S) Argument(_ interface{}) {
}
func (_ *S) Result() interface{} {
return nil
}
type I interface {
Argument(_ interface{})
Result() interface{}
}
var (
Uint uint
Uint32 uint32
Uint64 uint64
C64 complex64 = 0
C128 complex128 = 0
)
const (
Cuint uint = 0
Cuint32 uint32 = 0
Cuint64 uint64 = 0
)

63
bind/testdata/ignore.go.golden vendored Normal file
View file

@ -0,0 +1,63 @@
// Code generated by gobind. DO NOT EDIT.
// Package main is an autogenerated binder stub for package ignore.
//
// autogenerated by gobind -lang=go ignore
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "ignore.h"
*/
import "C"
import (
_seq "golang.org/x/mobile/bind/seq"
"ignore"
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
// skipped field S.F with unsupported type: interface{}
// skipped method S.Argument with unsupported parameter or return types
// skipped method S.Result with unsupported parameter or return types
//export new_ignore_S
func new_ignore_S() C.int32_t {
return C.int32_t(_seq.ToRefNum(new(ignore.S)))
}
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
type proxyignore_I _seq.Ref
func (p *proxyignore_I) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
// skipped method I.Argument with unsupported parameter or result types
// skipped method I.Result with unsupported parameter or result types
// skipped variable C128 with unsupported type complex128
// skipped variable C64 with unsupported type complex64
// skipped variable Uint with unsupported type uint
// skipped variable Uint32 with unsupported type uint32
// skipped variable Uint64 with unsupported type uint64
// skipped variable V with unsupported type interface{}
// skipped variable Var with unsupported type interface{}
// skipped function Argument with unsupported parameter or result types
// skipped function Result with unsupported parameter or result types

75
bind/testdata/ignore.java.c.golden vendored Normal file
View file

@ -0,0 +1,75 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java ignore
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "ignore.h"
jclass proxy_class_ignore_I;
jmethodID proxy_class_ignore_I_cons;
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
jclass proxy_class_ignore_S;
jmethodID proxy_class_ignore_S_cons;
JNIEXPORT void JNICALL
Java_ignore_Ignore__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
clazz = (*env)->FindClass(env, "ignore/S");
proxy_class_ignore_S = (*env)->NewGlobalRef(env, clazz);
proxy_class_ignore_S_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "ignore/Ignore$proxyI");
proxy_class_ignore_I = (*env)->NewGlobalRef(env, clazz);
proxy_class_ignore_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "ignore/I");
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
}
// skipped function Argument with unsupported parameter or return types
// skipped function Result with unsupported parameter or return types
JNIEXPORT jint JNICALL
Java_ignore_S__1_1New(JNIEnv *env, jclass clazz) {
return new_ignore_S();
}
// skipped function S.Argument with unsupported parameter or return types
// skipped function S.Result with unsupported parameter or return types
// skipped field S with unsupported type: interface{}
// skipped function I.Argument with unsupported parameter or return types
// skipped method I with unsupported parameter or return types
// skipped function I.Result with unsupported parameter or return types
// skipped method I with unsupported parameter or return types
// skipped variable C128 with unsupported type: complex128
// skipped variable C64 with unsupported type: complex64
// skipped variable Uint with unsupported type: uint
// skipped variable Uint32 with unsupported type: uint32
// skipped variable Uint64 with unsupported type: uint64
// skipped variable V with unsupported type: interface{}
// skipped variable Var with unsupported type: interface{}

135
bind/testdata/ignore.java.golden vendored Normal file
View file

@ -0,0 +1,135 @@
// Code generated by gobind. DO NOT EDIT.
// Java class ignore.S is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java ignore
package ignore;
import go.Seq;
public final class S implements Seq.Proxy, I {
static { Ignore.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
S(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public S() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
// skipped field S.F with unsupported type: interface{}
// skipped method S.Argument with unsupported parameter or return types
// skipped method S.Result with unsupported parameter or return types
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof S)) {
return false;
}
S that = (S)o;
// skipped field S.F with unsupported type: interface{}
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {});
}
@Override public String toString() {
StringBuilder b = new StringBuilder();
b.append("S").append("{");
return b.append("}").toString();
}
}
// Code generated by gobind. DO NOT EDIT.
// Java class ignore.I is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java ignore
package ignore;
import go.Seq;
public interface I {
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
}
// Code generated by gobind. DO NOT EDIT.
// Java class ignore.Ignore is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java ignore
package ignore;
import go.Seq;
public abstract class Ignore {
static {
Seq.touch(); // for loading the native library
_init();
}
private Ignore() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
private static final class proxyI implements Seq.Proxy, I {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
}
// skipped const Cuint with unsupported type: uint
// skipped const Cuint32 with unsupported type: uint32
// skipped const Cuint64 with unsupported type: uint64
// skipped const NamedConst with unsupported type: ignore.NamedString
// skipped variable C128 with unsupported type: complex128
// skipped variable C64 with unsupported type: complex64
// skipped variable Uint with unsupported type: uint
// skipped variable Uint32 with unsupported type: uint32
// skipped variable Uint64 with unsupported type: uint64
// skipped variable V with unsupported type: interface{}
// skipped variable Var with unsupported type: interface{}
// skipped function Argument with unsupported parameter or return types
// skipped function Result with unsupported parameter or return types
}

21
bind/testdata/ignore.java.h.golden vendored Normal file
View file

@ -0,0 +1,21 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java ignore
#ifndef __Ignore_H__
#define __Ignore_H__
#include <jni.h>
extern jclass proxy_class_ignore_I;
extern jmethodID proxy_class_ignore_I_cons;
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
extern jclass proxy_class_ignore_S;
extern jmethodID proxy_class_ignore_S_cons;
#endif

15
bind/testdata/ignore.objc.go.h.golden vendored Normal file
View file

@ -0,0 +1,15 @@
// Objective-C API for talking to ignore Go package.
// gobind -lang=objc ignore
//
// File is generated by gobind. Do not edit.
#ifndef __GO_ignore_H__
#define __GO_ignore_H__
#include <stdint.h>
#include <objc/objc.h>
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
#endif

84
bind/testdata/ignore.objc.h.golden vendored Normal file
View file

@ -0,0 +1,84 @@
// Objective-C API for talking to ignore Go package.
// gobind -lang=objc ignore
//
// File is generated by gobind. Do not edit.
#ifndef __Ignore_H__
#define __Ignore_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
@class IgnoreS;
@protocol IgnoreI;
@class IgnoreI;
@protocol IgnoreI <NSObject>
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
@end
@interface IgnoreS : NSObject <goSeqRefInterface, IgnoreI> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (nonnull instancetype)init;
// skipped field S.F with unsupported type: interface{}
// skipped method S.Argument with unsupported parameter or return types
// skipped method S.Result with unsupported parameter or return types
@end
// skipped const Cuint with unsupported type: uint
// skipped const Cuint32 with unsupported type: uint32
// skipped const Cuint64 with unsupported type: uint64
// skipped const NamedConst with unsupported type: ignore.NamedString
@interface Ignore : NSObject
// skipped variable C128 with unsupported type: complex128
// skipped variable C64 with unsupported type: complex64
// skipped variable Uint with unsupported type: uint
// skipped variable Uint32 with unsupported type: uint32
// skipped variable Uint64 with unsupported type: uint64
// skipped variable V with unsupported type: interface{}
// skipped variable Var with unsupported type: interface{}
@end
// skipped function Argument with unsupported parameter or return types
// skipped function Result with unsupported parameter or return types
@class IgnoreI;
@interface IgnoreI : NSObject <goSeqRefInterface, IgnoreI> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
@end
#endif

91
bind/testdata/ignore.objc.m.golden vendored Normal file
View file

@ -0,0 +1,91 @@
// Objective-C API for talking to ignore Go package.
// gobind -lang=objc ignore
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "Ignore.objc.h"
@implementation IgnoreS {
}
- (nonnull instancetype)initWithRef:(_Nonnull id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (nonnull instancetype)init {
self = [super init];
if (self) {
__ref = go_seq_from_refnum(new_ignore_S());
}
return self;
}
// skipped unsupported field F with type interface{}
// skipped method S.Argument with unsupported parameter or return types
// skipped method S.Result with unsupported parameter or return types
@end
@implementation IgnoreI {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
@end
// skipped const Cuint with unsupported type: uint
// skipped const Cuint32 with unsupported type: uint32
// skipped const Cuint64 with unsupported type: uint64
// skipped const NamedConst with unsupported type: ignore.NamedString
@implementation Ignore
// skipped variable C128 with unsupported type: complex128
// skipped variable C64 with unsupported type: complex64
// skipped variable Uint with unsupported type: uint
// skipped variable Uint32 with unsupported type: uint32
// skipped variable Uint64 with unsupported type: uint64
// skipped variable V with unsupported type: interface{}
// skipped variable Var with unsupported type: interface{}
@end
// skipped function Argument with unsupported parameter or return types
// skipped function Result with unsupported parameter or return types
// skipped method I.Argument with unsupported parameter or return types
// skipped method I.Result with unsupported parameter or return types
__attribute__((constructor)) static void init() {
init_seq();
}

69
bind/testdata/interfaces.go vendored Normal file
View file

@ -0,0 +1,69 @@
// Copyright 2014 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 interfaces
type I interface {
Rand() int32
}
type SameI interface {
Rand() int32
}
type LargerI interface {
Rand() int32
AnotherFunc()
}
func Add3(r I) int32 {
return r.Rand() + r.Rand() + r.Rand()
}
// chosen by fair dice roll.
// guaranteed to be random.
type seven struct{}
func (seven) Rand() int32 { return 7 }
func Seven() I { return seven{} }
type WithParam interface {
HasParam(p bool)
}
type Error interface {
Err() error
}
func CallErr(e Error) error {
return e.Err()
}
// not implementable
type I1 interface {
J()
H() *seven // not bound
}
// not implementable
type I2 interface {
f()
G()
}
// implementable
// (the implementor has to find a source of I1s)
type I3 interface {
F() I1
}
// not bound
func F() seven { return seven{} }
func G(u seven) {}
// Interfaces is an interface with the same name as its package.
type Interfaces interface {
SomeMethod()
}

257
bind/testdata/interfaces.go.golden vendored Normal file
View file

@ -0,0 +1,257 @@
// Code generated by gobind. DO NOT EDIT.
// Package main is an autogenerated binder stub for package interfaces.
//
// autogenerated by gobind -lang=go interfaces
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "interfaces.h"
*/
import "C"
import (
_seq "golang.org/x/mobile/bind/seq"
"interfaces"
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
//export proxyinterfaces_Error_Err
func proxyinterfaces_Error_Err(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.Error)
res_0 := v.Err()
var _res_0 C.int32_t = _seq.NullRefNum
if res_0 != nil {
_res_0 = C.int32_t(_seq.ToRefNum(res_0))
}
return _res_0
}
type proxyinterfaces_Error _seq.Ref
func (p *proxyinterfaces_Error) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_Error) Err() error {
res := C.cproxyinterfaces_Error_Err(C.int32_t(p.Bind_proxy_refnum__()))
var _res error
_res_ref := _seq.FromRefNum(int32(res))
if _res_ref != nil {
if res < 0 { // go object
_res = _res_ref.Get().(error)
} else { // foreign object
_res = (*proxy_error)(_res_ref)
}
}
return _res
}
//export proxyinterfaces_I_Rand
func proxyinterfaces_I_Rand(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.I)
res_0 := v.Rand()
_res_0 := C.int32_t(res_0)
return _res_0
}
type proxyinterfaces_I _seq.Ref
func (p *proxyinterfaces_I) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_I) Rand() int32 {
res := C.cproxyinterfaces_I_Rand(C.int32_t(p.Bind_proxy_refnum__()))
_res := int32(res)
return _res
}
//export proxyinterfaces_I1_J
func proxyinterfaces_I1_J(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.I1)
v.J()
}
//export proxyinterfaces_I2_G
func proxyinterfaces_I2_G(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.I2)
v.G()
}
//export proxyinterfaces_I3_F
func proxyinterfaces_I3_F(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.I3)
res_0 := v.F()
var _res_0 C.int32_t = _seq.NullRefNum
if res_0 != nil {
_res_0 = C.int32_t(_seq.ToRefNum(res_0))
}
return _res_0
}
type proxyinterfaces_I3 _seq.Ref
func (p *proxyinterfaces_I3) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_I3) F() interfaces.I1 {
res := C.cproxyinterfaces_I3_F(C.int32_t(p.Bind_proxy_refnum__()))
var _res interfaces.I1
_res_ref := _seq.FromRefNum(int32(res))
if _res_ref != nil {
if res < 0 { // go object
_res = _res_ref.Get().(interfaces.I1)
}
}
return _res
}
//export proxyinterfaces_Interfaces_SomeMethod
func proxyinterfaces_Interfaces_SomeMethod(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.Interfaces)
v.SomeMethod()
}
type proxyinterfaces_Interfaces _seq.Ref
func (p *proxyinterfaces_Interfaces) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_Interfaces) SomeMethod() {
C.cproxyinterfaces_Interfaces_SomeMethod(C.int32_t(p.Bind_proxy_refnum__()))
}
//export proxyinterfaces_LargerI_AnotherFunc
func proxyinterfaces_LargerI_AnotherFunc(refnum C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.LargerI)
v.AnotherFunc()
}
//export proxyinterfaces_LargerI_Rand
func proxyinterfaces_LargerI_Rand(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.LargerI)
res_0 := v.Rand()
_res_0 := C.int32_t(res_0)
return _res_0
}
type proxyinterfaces_LargerI _seq.Ref
func (p *proxyinterfaces_LargerI) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_LargerI) AnotherFunc() {
C.cproxyinterfaces_LargerI_AnotherFunc(C.int32_t(p.Bind_proxy_refnum__()))
}
func (p *proxyinterfaces_LargerI) Rand() int32 {
res := C.cproxyinterfaces_LargerI_Rand(C.int32_t(p.Bind_proxy_refnum__()))
_res := int32(res)
return _res
}
//export proxyinterfaces_SameI_Rand
func proxyinterfaces_SameI_Rand(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.SameI)
res_0 := v.Rand()
_res_0 := C.int32_t(res_0)
return _res_0
}
type proxyinterfaces_SameI _seq.Ref
func (p *proxyinterfaces_SameI) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_SameI) Rand() int32 {
res := C.cproxyinterfaces_SameI_Rand(C.int32_t(p.Bind_proxy_refnum__()))
_res := int32(res)
return _res
}
//export proxyinterfaces_WithParam_HasParam
func proxyinterfaces_WithParam_HasParam(refnum C.int32_t, param_p0 C.char) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(interfaces.WithParam)
_param_p0 := param_p0 != 0
v.HasParam(_param_p0)
}
type proxyinterfaces_WithParam _seq.Ref
func (p *proxyinterfaces_WithParam) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyinterfaces_WithParam) HasParam(param_p0 bool) {
var _param_p0 C.char = 0
if param_p0 {
_param_p0 = 1
}
C.cproxyinterfaces_WithParam_HasParam(C.int32_t(p.Bind_proxy_refnum__()), _param_p0)
}
//export proxyinterfaces__Add3
func proxyinterfaces__Add3(param_r C.int32_t) C.int32_t {
var _param_r interfaces.I
_param_r_ref := _seq.FromRefNum(int32(param_r))
if _param_r_ref != nil {
if param_r < 0 { // go object
_param_r = _param_r_ref.Get().(interfaces.I)
} else { // foreign object
_param_r = (*proxyinterfaces_I)(_param_r_ref)
}
}
res_0 := interfaces.Add3(_param_r)
_res_0 := C.int32_t(res_0)
return _res_0
}
//export proxyinterfaces__CallErr
func proxyinterfaces__CallErr(param_e C.int32_t) C.int32_t {
var _param_e interfaces.Error
_param_e_ref := _seq.FromRefNum(int32(param_e))
if _param_e_ref != nil {
if param_e < 0 { // go object
_param_e = _param_e_ref.Get().(interfaces.Error)
} else { // foreign object
_param_e = (*proxyinterfaces_Error)(_param_e_ref)
}
}
res_0 := interfaces.CallErr(_param_e)
var _res_0 C.int32_t = _seq.NullRefNum
if res_0 != nil {
_res_0 = C.int32_t(_seq.ToRefNum(res_0))
}
return _res_0
}
//export proxyinterfaces__Seven
func proxyinterfaces__Seven() C.int32_t {
res_0 := interfaces.Seven()
var _res_0 C.int32_t = _seq.NullRefNum
if res_0 != nil {
_res_0 = C.int32_t(_seq.ToRefNum(res_0))
}
return _res_0
}

277
bind/testdata/interfaces.java.c.golden vendored Normal file
View file

@ -0,0 +1,277 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java interfaces
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "interfaces.h"
jclass proxy_class_interfaces_Error;
jmethodID proxy_class_interfaces_Error_cons;
static jmethodID mid_Error_Err;
jclass proxy_class_interfaces_I;
jmethodID proxy_class_interfaces_I_cons;
static jmethodID mid_I_Rand;
jclass proxy_class_interfaces_I1;
jmethodID proxy_class_interfaces_I1_cons;
static jmethodID mid_I1_J;
jclass proxy_class_interfaces_I2;
jmethodID proxy_class_interfaces_I2_cons;
static jmethodID mid_I2_G;
jclass proxy_class_interfaces_I3;
jmethodID proxy_class_interfaces_I3_cons;
static jmethodID mid_I3_F;
jclass proxy_class_interfaces_Interfaces;
jmethodID proxy_class_interfaces_Interfaces_cons;
static jmethodID mid_Interfaces_SomeMethod;
jclass proxy_class_interfaces_LargerI;
jmethodID proxy_class_interfaces_LargerI_cons;
static jmethodID mid_LargerI_AnotherFunc;
static jmethodID mid_LargerI_Rand;
jclass proxy_class_interfaces_SameI;
jmethodID proxy_class_interfaces_SameI_cons;
static jmethodID mid_SameI_Rand;
jclass proxy_class_interfaces_WithParam;
jmethodID proxy_class_interfaces_WithParam_cons;
static jmethodID mid_WithParam_HasParam;
JNIEXPORT void JNICALL
Java_interfaces_Interfaces__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyError");
proxy_class_interfaces_Error = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_Error_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/Error");
mid_Error_Err = (*env)->GetMethodID(env, clazz, "err", "()V");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI");
proxy_class_interfaces_I = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_I_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/I");
mid_I_Rand = (*env)->GetMethodID(env, clazz, "rand", "()I");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI1");
proxy_class_interfaces_I1 = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_I1_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/I1");
mid_I1_J = (*env)->GetMethodID(env, clazz, "j", "()V");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI2");
proxy_class_interfaces_I2 = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_I2_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/I2");
mid_I2_G = (*env)->GetMethodID(env, clazz, "g", "()V");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyI3");
proxy_class_interfaces_I3 = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_I3_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/I3");
mid_I3_F = (*env)->GetMethodID(env, clazz, "f", "()Linterfaces/I1;");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyInterfaces");
proxy_class_interfaces_Interfaces = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_Interfaces_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/Interfaces_");
mid_Interfaces_SomeMethod = (*env)->GetMethodID(env, clazz, "someMethod", "()V");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyLargerI");
proxy_class_interfaces_LargerI = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_LargerI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/LargerI");
mid_LargerI_AnotherFunc = (*env)->GetMethodID(env, clazz, "anotherFunc", "()V");
mid_LargerI_Rand = (*env)->GetMethodID(env, clazz, "rand", "()I");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxySameI");
proxy_class_interfaces_SameI = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_SameI_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/SameI");
mid_SameI_Rand = (*env)->GetMethodID(env, clazz, "rand", "()I");
clazz = (*env)->FindClass(env, "interfaces/Interfaces$proxyWithParam");
proxy_class_interfaces_WithParam = (*env)->NewGlobalRef(env, clazz);
proxy_class_interfaces_WithParam_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "interfaces/WithParam");
mid_WithParam_HasParam = (*env)->GetMethodID(env, clazz, "hasParam", "(Z)V");
}
JNIEXPORT jint JNICALL
Java_interfaces_Interfaces_add3(JNIEnv* env, jclass _clazz, jobject r) {
int32_t _r = go_seq_to_refnum(env, r);
int32_t r0 = proxyinterfaces__Add3(_r);
jint _r0 = (jint)r0;
return _r0;
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_callErr(JNIEnv* env, jclass _clazz, jobject e) {
int32_t _e = go_seq_to_refnum(env, e);
int32_t r0 = proxyinterfaces__CallErr(_e);
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r0);
}
JNIEXPORT jobject JNICALL
Java_interfaces_Interfaces_seven(JNIEnv* env, jclass _clazz) {
int32_t r0 = proxyinterfaces__Seven();
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class_interfaces_I, proxy_class_interfaces_I_cons);
return _r0;
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_00024proxyError_err(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t r0 = proxyinterfaces_Error_Err(o);
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
go_seq_maybe_throw_exception(env, _r0);
}
int32_t cproxyinterfaces_Error_Err(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_Error, proxy_class_interfaces_Error_cons);
(*env)->CallVoidMethod(env, o, mid_Error_Err);
jobject exc = go_seq_get_exception(env);
int32_t _exc = go_seq_to_refnum(env, exc);
go_seq_pop_local_frame(env);
return _exc;
}
JNIEXPORT jint JNICALL
Java_interfaces_Interfaces_00024proxyI_rand(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t r0 = proxyinterfaces_I_Rand(o);
jint _r0 = (jint)r0;
return _r0;
}
int32_t cproxyinterfaces_I_Rand(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_I, proxy_class_interfaces_I_cons);
jint res = (*env)->CallIntMethod(env, o, mid_I_Rand);
int32_t _res = (int32_t)res;
go_seq_pop_local_frame(env);
return _res;
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_00024proxyI1_j(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxyinterfaces_I1_J(o);
}
void cproxyinterfaces_I1_J(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_I1, proxy_class_interfaces_I1_cons);
(*env)->CallVoidMethod(env, o, mid_I1_J);
go_seq_pop_local_frame(env);
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_00024proxyI2_g(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxyinterfaces_I2_G(o);
}
void cproxyinterfaces_I2_G(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_I2, proxy_class_interfaces_I2_cons);
(*env)->CallVoidMethod(env, o, mid_I2_G);
go_seq_pop_local_frame(env);
}
JNIEXPORT jobject JNICALL
Java_interfaces_Interfaces_00024proxyI3_f(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t r0 = proxyinterfaces_I3_F(o);
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class_interfaces_I1, proxy_class_interfaces_I1_cons);
return _r0;
}
int32_t cproxyinterfaces_I3_F(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_I3, proxy_class_interfaces_I3_cons);
jobject res = (*env)->CallObjectMethod(env, o, mid_I3_F);
int32_t _res = go_seq_to_refnum(env, res);
go_seq_pop_local_frame(env);
return _res;
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_00024proxyInterfaces_someMethod(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxyinterfaces_Interfaces_SomeMethod(o);
}
void cproxyinterfaces_Interfaces_SomeMethod(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_Interfaces, proxy_class_interfaces_Interfaces_cons);
(*env)->CallVoidMethod(env, o, mid_Interfaces_SomeMethod);
go_seq_pop_local_frame(env);
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_00024proxyLargerI_anotherFunc(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
proxyinterfaces_LargerI_AnotherFunc(o);
}
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_LargerI, proxy_class_interfaces_LargerI_cons);
(*env)->CallVoidMethod(env, o, mid_LargerI_AnotherFunc);
go_seq_pop_local_frame(env);
}
JNIEXPORT jint JNICALL
Java_interfaces_Interfaces_00024proxyLargerI_rand(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t r0 = proxyinterfaces_LargerI_Rand(o);
jint _r0 = (jint)r0;
return _r0;
}
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_LargerI, proxy_class_interfaces_LargerI_cons);
jint res = (*env)->CallIntMethod(env, o, mid_LargerI_Rand);
int32_t _res = (int32_t)res;
go_seq_pop_local_frame(env);
return _res;
}
JNIEXPORT jint JNICALL
Java_interfaces_Interfaces_00024proxySameI_rand(JNIEnv* env, jobject __this__) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t r0 = proxyinterfaces_SameI_Rand(o);
jint _r0 = (jint)r0;
return _r0;
}
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum) {
JNIEnv *env = go_seq_push_local_frame(0);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_SameI, proxy_class_interfaces_SameI_cons);
jint res = (*env)->CallIntMethod(env, o, mid_SameI_Rand);
int32_t _res = (int32_t)res;
go_seq_pop_local_frame(env);
return _res;
}
JNIEXPORT void JNICALL
Java_interfaces_Interfaces_00024proxyWithParam_hasParam(JNIEnv* env, jobject __this__, jboolean p0) {
int32_t o = go_seq_to_refnum_go(env, __this__);
char _p0 = (char)p0;
proxyinterfaces_WithParam_HasParam(o, _p0);
}
void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0) {
JNIEnv *env = go_seq_push_local_frame(1);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_interfaces_WithParam, proxy_class_interfaces_WithParam_cons);
jboolean _p0 = p0 ? JNI_TRUE : JNI_FALSE;
(*env)->CallVoidMethod(env, o, mid_WithParam_HasParam, _p0);
go_seq_pop_local_frame(env);
}

277
bind/testdata/interfaces.java.golden vendored Normal file
View file

@ -0,0 +1,277 @@
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.Error is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
public interface Error {
public void err() throws Exception;
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.I is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
public interface I {
public int rand();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.I1 is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
/**
* not implementable
*/
public interface I1 {
public void j();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.I2 is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
/**
* not implementable
*/
public interface I2 {
public void g();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.I3 is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
/**
* implementable
(the implementor has to find a source of I1s)
*/
public interface I3 {
public I1 f();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.Interfaces_ is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
/**
* Interfaces is an interface with the same name as its package.
*/
public interface Interfaces_ {
public void someMethod();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.LargerI is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
public interface LargerI extends I, SameI {
public void anotherFunc();
public int rand();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.SameI is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
public interface SameI {
public int rand();
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.WithParam is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
public interface WithParam {
public void hasParam(boolean p0);
}
// Code generated by gobind. DO NOT EDIT.
// Java class interfaces.Interfaces is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java interfaces
package interfaces;
import go.Seq;
public abstract class Interfaces {
static {
Seq.touch(); // for loading the native library
_init();
}
private Interfaces() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
private static final class proxyError implements Seq.Proxy, Error {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyError(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void err() throws Exception;
}
private static final class proxyI implements Seq.Proxy, I {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native int rand();
}
private static final class proxyI1 implements Seq.Proxy, I1 {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyI1(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void j();
}
private static final class proxyI2 implements Seq.Proxy, I2 {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyI2(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void g();
}
private static final class proxyI3 implements Seq.Proxy, I3 {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyI3(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native I1 f();
}
private static final class proxyInterfaces implements Seq.Proxy, Interfaces_ {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyInterfaces(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void someMethod();
}
private static final class proxyLargerI implements Seq.Proxy, LargerI {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyLargerI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void anotherFunc();
public native int rand();
}
private static final class proxySameI implements Seq.Proxy, SameI {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxySameI(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native int rand();
}
private static final class proxyWithParam implements Seq.Proxy, WithParam {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyWithParam(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void hasParam(boolean p0);
}
public static native int add3(I r);
public static native void callErr(Error e) throws Exception;
public static native I seven();
}

59
bind/testdata/interfaces.java.h.golden vendored Normal file
View file

@ -0,0 +1,59 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java interfaces
#ifndef __Interfaces_H__
#define __Interfaces_H__
#include <jni.h>
extern jclass proxy_class_interfaces_Error;
extern jmethodID proxy_class_interfaces_Error_cons;
int32_t 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_Interfaces;
extern jmethodID proxy_class_interfaces_Interfaces_cons;
void cproxyinterfaces_Interfaces_SomeMethod(int32_t refnum);
extern jclass proxy_class_interfaces_LargerI;
extern jmethodID proxy_class_interfaces_LargerI_cons;
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum);
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum);
extern jclass proxy_class_interfaces_SameI;
extern jmethodID proxy_class_interfaces_SameI_cons;
int32_t cproxyinterfaces_SameI_Rand(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

@ -0,0 +1,27 @@
// Objective-C API for talking to interfaces Go package.
// gobind -lang=objc interfaces
//
// File is generated by gobind. Do not edit.
#ifndef __GO_interfaces_H__
#define __GO_interfaces_H__
#include <stdint.h>
#include <objc/objc.h>
int32_t cproxyinterfaces_Error_Err(int32_t refnum);
int32_t cproxyinterfaces_I_Rand(int32_t refnum);
int32_t cproxyinterfaces_I3_F(int32_t refnum);
void cproxyinterfaces_Interfaces_SomeMethod(int32_t refnum);
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum);
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum);
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum);
void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0);
#endif

166
bind/testdata/interfaces.objc.h.golden vendored Normal file
View file

@ -0,0 +1,166 @@
// Objective-C API for talking to interfaces Go package.
// gobind -lang=objc interfaces
//
// File is generated by gobind. Do not edit.
#ifndef __Interfaces_H__
#define __Interfaces_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
@protocol InterfacesError;
@class InterfacesError;
@protocol InterfacesI;
@class InterfacesI;
@protocol InterfacesI1;
@protocol InterfacesI2;
@protocol InterfacesI3;
@class InterfacesI3;
@protocol InterfacesInterfaces;
@class InterfacesInterfaces;
@protocol InterfacesLargerI;
@class InterfacesLargerI;
@protocol InterfacesSameI;
@class InterfacesSameI;
@protocol InterfacesWithParam;
@class InterfacesWithParam;
@protocol InterfacesError <NSObject>
- (BOOL)err:(NSError* _Nullable* _Nullable)error;
@end
@protocol InterfacesI <NSObject>
- (int32_t)rand;
@end
/**
* not implementable
*/
@interface InterfacesI1 : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (void)j;
@end
/**
* not implementable
*/
@interface InterfacesI2 : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (void)g;
@end
@protocol InterfacesI3 <NSObject>
- (InterfacesI1* _Nullable)f;
@end
@protocol InterfacesInterfaces <NSObject>
- (void)someMethod;
@end
@protocol InterfacesLargerI <NSObject>
- (void)anotherFunc;
- (int32_t)rand;
@end
@protocol InterfacesSameI <NSObject>
- (int32_t)rand;
@end
@protocol InterfacesWithParam <NSObject>
- (void)hasParam:(BOOL)p0;
@end
FOUNDATION_EXPORT int32_t InterfacesAdd3(id<InterfacesI> _Nullable r);
FOUNDATION_EXPORT BOOL InterfacesCallErr(id<InterfacesError> _Nullable e, NSError* _Nullable* _Nullable error);
FOUNDATION_EXPORT id<InterfacesI> _Nullable InterfacesSeven(void);
@class InterfacesError;
@class InterfacesI;
@class InterfacesI3;
@class InterfacesInterfaces;
@class InterfacesLargerI;
@class InterfacesSameI;
@class InterfacesWithParam;
@interface InterfacesError : NSObject <goSeqRefInterface, InterfacesError> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (BOOL)err:(NSError* _Nullable* _Nullable)error;
@end
@interface InterfacesI : NSObject <goSeqRefInterface, InterfacesI> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (int32_t)rand;
@end
/**
* implementable
(the implementor has to find a source of I1s)
*/
@interface InterfacesI3 : NSObject <goSeqRefInterface, InterfacesI3> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (InterfacesI1* _Nullable)f;
@end
/**
* Interfaces is an interface with the same name as its package.
*/
@interface InterfacesInterfaces : NSObject <goSeqRefInterface, InterfacesInterfaces> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (void)someMethod;
@end
@interface InterfacesLargerI : NSObject <goSeqRefInterface, InterfacesLargerI> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (void)anotherFunc;
- (int32_t)rand;
@end
@interface InterfacesSameI : NSObject <goSeqRefInterface, InterfacesSameI> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (int32_t)rand;
@end
@interface InterfacesWithParam : NSObject <goSeqRefInterface, InterfacesWithParam> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (void)hasParam:(BOOL)p0;
@end
#endif

351
bind/testdata/interfaces.objc.m.golden vendored Normal file
View file

@ -0,0 +1,351 @@
// Objective-C API for talking to interfaces Go package.
// gobind -lang=objc interfaces
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "Interfaces.objc.h"
@implementation InterfacesError {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (BOOL)err:(NSError* _Nullable* _Nullable)error {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_Error_Err(refnum);
Universeerror* _error = nil;
GoSeqRef* _error_ref = go_seq_from_refnum(r0);
if (_error_ref != NULL) {
_error = _error_ref.obj;
if (_error == nil) {
_error = [[Universeerror alloc] initWithRef:_error_ref];
}
}
if (_error != nil && error != nil) {
*error = _error;
}
return (_error == nil);
}
@end
@implementation InterfacesI {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (int32_t)rand {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_I_Rand(refnum);
int32_t _ret0_ = (int32_t)r0;
return _ret0_;
}
@end
@implementation InterfacesI1 {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)j {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxyinterfaces_I1_J(refnum);
}
@end
@implementation InterfacesI2 {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)g {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxyinterfaces_I2_G(refnum);
}
@end
@implementation InterfacesI3 {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (InterfacesI1* _Nullable)f {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_I3_F(refnum);
InterfacesI1* _ret0_ = nil;
GoSeqRef* _ret0__ref = go_seq_from_refnum(r0);
if (_ret0__ref != NULL) {
_ret0_ = _ret0__ref.obj;
if (_ret0_ == nil) {
_ret0_ = [[InterfacesI1 alloc] initWithRef:_ret0__ref];
}
}
return _ret0_;
}
@end
@implementation InterfacesInterfaces {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)someMethod {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxyinterfaces_Interfaces_SomeMethod(refnum);
}
@end
@implementation InterfacesLargerI {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)anotherFunc {
int32_t refnum = go_seq_go_to_refnum(self._ref);
proxyinterfaces_LargerI_AnotherFunc(refnum);
}
- (int32_t)rand {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_LargerI_Rand(refnum);
int32_t _ret0_ = (int32_t)r0;
return _ret0_;
}
@end
@implementation InterfacesSameI {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (int32_t)rand {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t r0 = proxyinterfaces_SameI_Rand(refnum);
int32_t _ret0_ = (int32_t)r0;
return _ret0_;
}
@end
@implementation InterfacesWithParam {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)hasParam:(BOOL)p0 {
int32_t refnum = go_seq_go_to_refnum(self._ref);
char _p0 = (char)p0;
proxyinterfaces_WithParam_HasParam(refnum, _p0);
}
@end
int32_t InterfacesAdd3(id<InterfacesI> _Nullable r) {
int32_t _r;
if ([r conformsToProtocol:@protocol(goSeqRefInterface)]) {
id<goSeqRefInterface> r_proxy = (id<goSeqRefInterface>)(r);
_r = go_seq_go_to_refnum(r_proxy._ref);
} else {
_r = go_seq_to_refnum(r);
}
int32_t r0 = proxyinterfaces__Add3(_r);
int32_t _ret0_ = (int32_t)r0;
return _ret0_;
}
BOOL InterfacesCallErr(id<InterfacesError> _Nullable e, NSError* _Nullable* _Nullable error) {
int32_t _e;
if ([e conformsToProtocol:@protocol(goSeqRefInterface)]) {
id<goSeqRefInterface> e_proxy = (id<goSeqRefInterface>)(e);
_e = go_seq_go_to_refnum(e_proxy._ref);
} else {
_e = go_seq_to_refnum(e);
}
int32_t r0 = proxyinterfaces__CallErr(_e);
Universeerror* _error = nil;
GoSeqRef* _error_ref = go_seq_from_refnum(r0);
if (_error_ref != NULL) {
_error = _error_ref.obj;
if (_error == nil) {
_error = [[Universeerror alloc] initWithRef:_error_ref];
}
}
if (_error != nil && error != nil) {
*error = _error;
}
return (_error == nil);
}
id<InterfacesI> _Nullable InterfacesSeven(void) {
int32_t r0 = proxyinterfaces__Seven();
InterfacesI* _ret0_ = nil;
GoSeqRef* _ret0__ref = go_seq_from_refnum(r0);
if (_ret0__ref != NULL) {
_ret0_ = _ret0__ref.obj;
if (_ret0_ == nil) {
_ret0_ = [[InterfacesI alloc] initWithRef:_ret0__ref];
}
}
return _ret0_;
}
int32_t cproxyinterfaces_Error_Err(int32_t refnum) {
@autoreleasepool {
InterfacesError* o = go_seq_objc_from_refnum(refnum);
NSError* error = nil;
BOOL returnVal = [o err:&error];
NSError *_error = nil;
if (!returnVal) {
_error = error;
}
int32_t __error;
if ([_error conformsToProtocol:@protocol(goSeqRefInterface)]) {
id<goSeqRefInterface> _error_proxy = (id<goSeqRefInterface>)(_error);
__error = go_seq_go_to_refnum(_error_proxy._ref);
} else {
__error = go_seq_to_refnum(_error);
}
return __error;
}
}
int32_t cproxyinterfaces_I_Rand(int32_t refnum) {
@autoreleasepool {
InterfacesI* o = go_seq_objc_from_refnum(refnum);
int32_t ret0_;
ret0_ = [o rand];
int32_t _ret0_ = (int32_t)ret0_;
return _ret0_;
}
}
void cproxyinterfaces_I1_J(int32_t refnum) {
@autoreleasepool {
InterfacesI1* o = go_seq_objc_from_refnum(refnum);
[o j];
}
}
void cproxyinterfaces_I2_G(int32_t refnum) {
@autoreleasepool {
InterfacesI2* o = go_seq_objc_from_refnum(refnum);
[o g];
}
}
int32_t cproxyinterfaces_I3_F(int32_t refnum) {
@autoreleasepool {
InterfacesI3* o = go_seq_objc_from_refnum(refnum);
InterfacesI1* _Nullable ret0_;
ret0_ = [o f];
int32_t _ret0_;
if ([ret0_ conformsToProtocol:@protocol(goSeqRefInterface)]) {
id<goSeqRefInterface> ret0__proxy = (id<goSeqRefInterface>)(ret0_);
_ret0_ = go_seq_go_to_refnum(ret0__proxy._ref);
} else {
_ret0_ = go_seq_to_refnum(ret0_);
}
return _ret0_;
}
}
void cproxyinterfaces_Interfaces_SomeMethod(int32_t refnum) {
@autoreleasepool {
InterfacesInterfaces* o = go_seq_objc_from_refnum(refnum);
[o someMethod];
}
}
void cproxyinterfaces_LargerI_AnotherFunc(int32_t refnum) {
@autoreleasepool {
InterfacesLargerI* o = go_seq_objc_from_refnum(refnum);
[o anotherFunc];
}
}
int32_t cproxyinterfaces_LargerI_Rand(int32_t refnum) {
@autoreleasepool {
InterfacesLargerI* o = go_seq_objc_from_refnum(refnum);
int32_t ret0_;
ret0_ = [o rand];
int32_t _ret0_ = (int32_t)ret0_;
return _ret0_;
}
}
int32_t cproxyinterfaces_SameI_Rand(int32_t refnum) {
@autoreleasepool {
InterfacesSameI* o = go_seq_objc_from_refnum(refnum);
int32_t ret0_;
ret0_ = [o rand];
int32_t _ret0_ = (int32_t)ret0_;
return _ret0_;
}
}
void cproxyinterfaces_WithParam_HasParam(int32_t refnum, char p0) {
@autoreleasepool {
InterfacesWithParam* o = go_seq_objc_from_refnum(refnum);
BOOL _p0 = p0 ? YES : NO;
[o hasParam:_p0];
}
}
__attribute__((constructor)) static void init() {
init_seq();
}

14
bind/testdata/issue10788.go vendored Normal file
View file

@ -0,0 +1,14 @@
// Copyright 2015 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 issue10788
type TestStruct struct {
Value string
}
type TestInterface interface {
DoSomeWork(s *TestStruct)
MultipleUnnamedParams(_ int, p0 string, 日本 int64)
}

86
bind/testdata/issue10788.go.golden vendored Normal file
View file

@ -0,0 +1,86 @@
// Code generated by gobind. DO NOT EDIT.
// Package main is an autogenerated binder stub for package issue10788.
//
// autogenerated by gobind -lang=go issue10788
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "issue10788.h"
*/
import "C"
import (
_seq "golang.org/x/mobile/bind/seq"
"issue10788"
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
//export proxyissue10788_TestStruct_Value_Set
func proxyissue10788_TestStruct_Value_Set(refnum C.int32_t, v C.nstring) {
ref := _seq.FromRefNum(int32(refnum))
_v := decodeString(v)
ref.Get().(*issue10788.TestStruct).Value = _v
}
//export proxyissue10788_TestStruct_Value_Get
func proxyissue10788_TestStruct_Value_Get(refnum C.int32_t) C.nstring {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*issue10788.TestStruct).Value
_v := encodeString(v)
return _v
}
//export new_issue10788_TestStruct
func new_issue10788_TestStruct() C.int32_t {
return C.int32_t(_seq.ToRefNum(new(issue10788.TestStruct)))
}
//export proxyissue10788_TestInterface_DoSomeWork
func proxyissue10788_TestInterface_DoSomeWork(refnum C.int32_t, param_s C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(issue10788.TestInterface)
// Must be a Go object
var _param_s *issue10788.TestStruct
if _param_s_ref := _seq.FromRefNum(int32(param_s)); _param_s_ref != nil {
_param_s = _param_s_ref.Get().(*issue10788.TestStruct)
}
v.DoSomeWork(_param_s)
}
//export proxyissue10788_TestInterface_MultipleUnnamedParams
func proxyissue10788_TestInterface_MultipleUnnamedParams(refnum C.int32_t, param_p0 C.nint, param_p1 C.nstring, param_日本 C.int64_t) {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(issue10788.TestInterface)
_param_p0 := int(param_p0)
_param_p1 := decodeString(param_p1)
_param_日本 := int64(param_日本)
v.MultipleUnnamedParams(_param_p0, _param_p1, _param_日本)
}
type proxyissue10788_TestInterface _seq.Ref
func (p *proxyissue10788_TestInterface) Bind_proxy_refnum__() int32 {
return (*_seq.Ref)(p).Bind_IncNum()
}
func (p *proxyissue10788_TestInterface) DoSomeWork(param_s *issue10788.TestStruct) {
var _param_s C.int32_t = _seq.NullRefNum
if param_s != nil {
_param_s = C.int32_t(_seq.ToRefNum(param_s))
}
C.cproxyissue10788_TestInterface_DoSomeWork(C.int32_t(p.Bind_proxy_refnum__()), _param_s)
}
func (p *proxyissue10788_TestInterface) MultipleUnnamedParams(param_p0 int, param_p1 string, param_日本 int64) {
_param_p0 := C.nint(param_p0)
_param_p1 := encodeString(param_p1)
_param_日本 := C.int64_t(param_日本)
C.cproxyissue10788_TestInterface_MultipleUnnamedParams(C.int32_t(p.Bind_proxy_refnum__()), _param_p0, _param_p1, _param_日本)
}

88
bind/testdata/issue10788.java.c.golden vendored Normal file
View file

@ -0,0 +1,88 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java issue10788
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "issue10788.h"
jclass proxy_class_issue10788_TestInterface;
jmethodID proxy_class_issue10788_TestInterface_cons;
static jmethodID mid_TestInterface_DoSomeWork;
static jmethodID mid_TestInterface_MultipleUnnamedParams;
jclass proxy_class_issue10788_TestStruct;
jmethodID proxy_class_issue10788_TestStruct_cons;
JNIEXPORT void JNICALL
Java_issue10788_Issue10788__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
clazz = (*env)->FindClass(env, "issue10788/TestStruct");
proxy_class_issue10788_TestStruct = (*env)->NewGlobalRef(env, clazz);
proxy_class_issue10788_TestStruct_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "issue10788/Issue10788$proxyTestInterface");
proxy_class_issue10788_TestInterface = (*env)->NewGlobalRef(env, clazz);
proxy_class_issue10788_TestInterface_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
clazz = (*env)->FindClass(env, "issue10788/TestInterface");
mid_TestInterface_DoSomeWork = (*env)->GetMethodID(env, clazz, "doSomeWork", "(Lissue10788/TestStruct;)V");
mid_TestInterface_MultipleUnnamedParams = (*env)->GetMethodID(env, clazz, "multipleUnnamedParams", "(JLjava/lang/String;J)V");
}
JNIEXPORT jint JNICALL
Java_issue10788_TestStruct__1_1New(JNIEnv *env, jclass clazz) {
return new_issue10788_TestStruct();
}
JNIEXPORT void JNICALL
Java_issue10788_TestStruct_setValue(JNIEnv *env, jobject this, jstring v) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring _v = go_seq_from_java_string(env, v);
proxyissue10788_TestStruct_Value_Set(o, _v);
}
JNIEXPORT jstring JNICALL
Java_issue10788_TestStruct_getValue(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
nstring r0 = proxyissue10788_TestStruct_Value_Get(o);
jstring _r0 = go_seq_to_java_string(env, r0);
return _r0;
}
JNIEXPORT void JNICALL
Java_issue10788_Issue10788_00024proxyTestInterface_doSomeWork(JNIEnv* env, jobject __this__, jobject s) {
int32_t o = go_seq_to_refnum_go(env, __this__);
int32_t _s = go_seq_to_refnum(env, s);
proxyissue10788_TestInterface_DoSomeWork(o, _s);
}
void cproxyissue10788_TestInterface_DoSomeWork(int32_t refnum, int32_t s) {
JNIEnv *env = go_seq_push_local_frame(1);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_issue10788_TestInterface, proxy_class_issue10788_TestInterface_cons);
jobject _s = go_seq_from_refnum(env, s, proxy_class_issue10788_TestStruct, proxy_class_issue10788_TestStruct_cons);
(*env)->CallVoidMethod(env, o, mid_TestInterface_DoSomeWork, _s);
go_seq_pop_local_frame(env);
}
JNIEXPORT void JNICALL
Java_issue10788_Issue10788_00024proxyTestInterface_multipleUnnamedParams(JNIEnv* env, jobject __this__, jlong p0, jstring p1, jlong p2) {
int32_t o = go_seq_to_refnum_go(env, __this__);
nint _p0 = (nint)p0;
nstring _p1 = go_seq_from_java_string(env, p1);
int64_t _p2 = (int64_t)p2;
proxyissue10788_TestInterface_MultipleUnnamedParams(o, _p0, _p1, _p2);
}
void cproxyissue10788_TestInterface_MultipleUnnamedParams(int32_t refnum, nint p0, nstring p1, int64_t p2) {
JNIEnv *env = go_seq_push_local_frame(3);
jobject o = go_seq_from_refnum(env, refnum, proxy_class_issue10788_TestInterface, proxy_class_issue10788_TestInterface_cons);
jlong _p0 = (jlong)p0;
jstring _p1 = go_seq_to_java_string(env, p1);
jlong _p2 = (jlong)p2;
(*env)->CallVoidMethod(env, o, mid_TestInterface_MultipleUnnamedParams, _p0, _p1, _p2);
go_seq_pop_local_frame(env);
}

110
bind/testdata/issue10788.java.golden vendored Normal file
View file

@ -0,0 +1,110 @@
// Code generated by gobind. DO NOT EDIT.
// Java class issue10788.TestStruct is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java issue10788
package issue10788;
import go.Seq;
public final class TestStruct implements Seq.Proxy {
static { Issue10788.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
TestStruct(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public TestStruct() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
public final native String getValue();
public final native void setValue(String v);
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof TestStruct)) {
return false;
}
TestStruct that = (TestStruct)o;
String thisValue = getValue();
String thatValue = that.getValue();
if (thisValue == null) {
if (thatValue != null) {
return false;
}
} else if (!thisValue.equals(thatValue)) {
return false;
}
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {getValue()});
}
@Override public String toString() {
StringBuilder b = new StringBuilder();
b.append("TestStruct").append("{");
b.append("Value:").append(getValue()).append(",");
return b.append("}").toString();
}
}
// Code generated by gobind. DO NOT EDIT.
// Java class issue10788.TestInterface is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java issue10788
package issue10788;
import go.Seq;
public interface TestInterface {
public void doSomeWork(TestStruct s);
public void multipleUnnamedParams(long p0, String p1, long p2);
}
// Code generated by gobind. DO NOT EDIT.
// Java class issue10788.Issue10788 is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java issue10788
package issue10788;
import go.Seq;
public abstract class Issue10788 {
static {
Seq.touch(); // for loading the native library
_init();
}
private Issue10788() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
private static final class proxyTestInterface implements Seq.Proxy, TestInterface {
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
proxyTestInterface(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public native void doSomeWork(TestStruct s);
public native void multipleUnnamedParams(long p0, String p1, long p2);
}
}

21
bind/testdata/issue10788.java.h.golden vendored Normal file
View file

@ -0,0 +1,21 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java issue10788
#ifndef __Issue10788_H__
#define __Issue10788_H__
#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

@ -0,0 +1,15 @@
// Objective-C API for talking to issue10788 Go package.
// gobind -lang=objc issue10788
//
// File is generated by gobind. Do not edit.
#ifndef __GO_issue10788_H__
#define __GO_issue10788_H__
#include <stdint.h>
#include <objc/objc.h>
void cproxyissue10788_TestInterface_DoSomeWork(int32_t refnum, int32_t s);
void cproxyissue10788_TestInterface_MultipleUnnamedParams(int32_t refnum, nint p0, nstring p1, int64_t 日本);
#endif

43
bind/testdata/issue10788.objc.h.golden vendored Normal file
View file

@ -0,0 +1,43 @@
// Objective-C API for talking to issue10788 Go package.
// gobind -lang=objc issue10788
//
// File is generated by gobind. Do not edit.
#ifndef __Issue10788_H__
#define __Issue10788_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
@class Issue10788TestStruct;
@protocol Issue10788TestInterface;
@class Issue10788TestInterface;
@protocol Issue10788TestInterface <NSObject>
- (void)doSomeWork:(Issue10788TestStruct* _Nullable)s;
- (void)multipleUnnamedParams:(long)p0 p1:(NSString* _Nullable)p1 日本:(int64_t)日本;
@end
@interface Issue10788TestStruct : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (nonnull instancetype)init;
@property (nonatomic) NSString* _Nonnull value;
@end
@class Issue10788TestInterface;
@interface Issue10788TestInterface : NSObject <goSeqRefInterface, Issue10788TestInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (void)doSomeWork:(Issue10788TestStruct* _Nullable)s;
- (void)multipleUnnamedParams:(long)p0 p1:(NSString* _Nullable)p1 日本:(int64_t)日本;
@end
#endif

105
bind/testdata/issue10788.objc.m.golden vendored Normal file
View file

@ -0,0 +1,105 @@
// Objective-C API for talking to issue10788 Go package.
// gobind -lang=objc issue10788
//
// File is generated by gobind. Do not edit.
#include <Foundation/Foundation.h>
#include "seq.h"
#include "_cgo_export.h"
#include "Issue10788.objc.h"
@implementation Issue10788TestStruct {
}
- (nonnull instancetype)initWithRef:(_Nonnull id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (nonnull instancetype)init {
self = [super init];
if (self) {
__ref = go_seq_from_refnum(new_issue10788_TestStruct());
}
return self;
}
- (NSString* _Nonnull)value {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring r0 = proxyissue10788_TestStruct_Value_Get(refnum);
NSString *_r0 = go_seq_to_objc_string(r0);
return _r0;
}
- (void)setValue:(NSString* _Nonnull)v {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nstring _v = go_seq_from_objc_string(v);
proxyissue10788_TestStruct_Value_Set(refnum, _v);
}
@end
@implementation Issue10788TestInterface {
}
- (nonnull instancetype)initWithRef:(id)ref {
self = [super init];
if (self) { __ref = ref; }
return self;
}
- (void)doSomeWork:(Issue10788TestStruct* _Nullable)s {
int32_t refnum = go_seq_go_to_refnum(self._ref);
int32_t _s;
if ([s conformsToProtocol:@protocol(goSeqRefInterface)]) {
id<goSeqRefInterface> s_proxy = (id<goSeqRefInterface>)(s);
_s = go_seq_go_to_refnum(s_proxy._ref);
} else {
_s = go_seq_to_refnum(s);
}
proxyissue10788_TestInterface_DoSomeWork(refnum, _s);
}
- (void)multipleUnnamedParams:(long)p0 p1:(NSString* _Nullable)p1 日本:(int64_t)日本 {
int32_t refnum = go_seq_go_to_refnum(self._ref);
nint _p0 = (nint)p0;
nstring _p1 = go_seq_from_objc_string(p1);
int64_t _日本 = (int64_t)日本;
proxyissue10788_TestInterface_MultipleUnnamedParams(refnum, _p0, _p1, _日本);
}
@end
void cproxyissue10788_TestInterface_DoSomeWork(int32_t refnum, int32_t s) {
@autoreleasepool {
Issue10788TestInterface* o = go_seq_objc_from_refnum(refnum);
Issue10788TestStruct* _s = nil;
GoSeqRef* _s_ref = go_seq_from_refnum(s);
if (_s_ref != NULL) {
_s = _s_ref.obj;
if (_s == nil) {
_s = [[Issue10788TestStruct alloc] initWithRef:_s_ref];
}
}
[o doSomeWork:_s];
}
}
void cproxyissue10788_TestInterface_MultipleUnnamedParams(int32_t refnum, nint p0, nstring p1, int64_t 日本) {
@autoreleasepool {
Issue10788TestInterface* o = go_seq_objc_from_refnum(refnum);
long _p0 = (long)p0;
NSString *_p1 = go_seq_to_objc_string(p1);
int64_t _日本 = (int64_t)日本;
[o multipleUnnamedParams:_p0 p1:_p1 日本:_日本];
}
}
__attribute__((constructor)) static void init() {
init_seq();
}

9
bind/testdata/issue12328.go vendored Normal file
View file

@ -0,0 +1,9 @@
// Copyright 2015 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 issue12328
type T struct {
Err error
}

54
bind/testdata/issue12328.go.golden vendored Normal file
View file

@ -0,0 +1,54 @@
// Code generated by gobind. DO NOT EDIT.
// Package main is an autogenerated binder stub for package issue12328.
//
// autogenerated by gobind -lang=go issue12328
package main
/*
#include <stdlib.h>
#include <stdint.h>
#include "seq.h"
#include "issue12328.h"
*/
import "C"
import (
_seq "golang.org/x/mobile/bind/seq"
"issue12328"
)
// suppress the error if seq ends up unused
var _ = _seq.FromRefNum
//export proxyissue12328_T_Err_Set
func proxyissue12328_T_Err_Set(refnum C.int32_t, v C.int32_t) {
ref := _seq.FromRefNum(int32(refnum))
var _v error
_v_ref := _seq.FromRefNum(int32(v))
if _v_ref != nil {
if v < 0 { // go object
_v = _v_ref.Get().(error)
} else { // foreign object
_v = (*proxy_error)(_v_ref)
}
}
ref.Get().(*issue12328.T).Err = _v
}
//export proxyissue12328_T_Err_Get
func proxyissue12328_T_Err_Get(refnum C.int32_t) C.int32_t {
ref := _seq.FromRefNum(int32(refnum))
v := ref.Get().(*issue12328.T).Err
var _v C.int32_t = _seq.NullRefNum
if v != nil {
_v = C.int32_t(_seq.ToRefNum(v))
}
return _v
}
//export new_issue12328_T
func new_issue12328_T() C.int32_t {
return C.int32_t(_seq.ToRefNum(new(issue12328.T)))
}

43
bind/testdata/issue12328.java.c.golden vendored Normal file
View file

@ -0,0 +1,43 @@
// Code generated by gobind. DO NOT EDIT.
// JNI functions for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java issue12328
#include <android/log.h>
#include <stdint.h>
#include "seq.h"
#include "_cgo_export.h"
#include "issue12328.h"
jclass proxy_class_issue12328_T;
jmethodID proxy_class_issue12328_T_cons;
JNIEXPORT void JNICALL
Java_issue12328_Issue12328__1init(JNIEnv *env, jclass _unused) {
jclass clazz;
clazz = (*env)->FindClass(env, "issue12328/T");
proxy_class_issue12328_T = (*env)->NewGlobalRef(env, clazz);
proxy_class_issue12328_T_cons = (*env)->GetMethodID(env, clazz, "<init>", "(I)V");
}
JNIEXPORT jint JNICALL
Java_issue12328_T__1_1New(JNIEnv *env, jclass clazz) {
return new_issue12328_T();
}
JNIEXPORT void JNICALL
Java_issue12328_T_setErr(JNIEnv *env, jobject this, jobject v) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t _v = go_seq_to_refnum(env, v);
proxyissue12328_T_Err_Set(o, _v);
}
JNIEXPORT jobject JNICALL
Java_issue12328_T_getErr(JNIEnv *env, jobject this) {
int32_t o = go_seq_to_refnum_go(env, this);
int32_t r0 = proxyissue12328_T_Err_Get(o);
jobject _r0 = go_seq_from_refnum(env, r0, proxy_class__error, proxy_class__error_cons);
return _r0;
}

82
bind/testdata/issue12328.java.golden vendored Normal file
View file

@ -0,0 +1,82 @@
// Code generated by gobind. DO NOT EDIT.
// Java class issue12328.T is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java issue12328
package issue12328;
import go.Seq;
public final class T implements Seq.Proxy {
static { Issue12328.touch(); }
private final int refnum;
@Override public final int incRefnum() {
Seq.incGoRef(refnum, this);
return refnum;
}
T(int refnum) { this.refnum = refnum; Seq.trackGoRef(refnum, this); }
public T() { this.refnum = __New(); Seq.trackGoRef(refnum, this); }
private static native int __New();
public final native java.lang.Exception getErr();
public final native void setErr(java.lang.Exception v);
@Override public boolean equals(Object o) {
if (o == null || !(o instanceof T)) {
return false;
}
T that = (T)o;
java.lang.Exception thisErr = getErr();
java.lang.Exception thatErr = that.getErr();
if (thisErr == null) {
if (thatErr != null) {
return false;
}
} else if (!thisErr.equals(thatErr)) {
return false;
}
return true;
}
@Override public int hashCode() {
return java.util.Arrays.hashCode(new Object[] {getErr()});
}
@Override public String toString() {
StringBuilder b = new StringBuilder();
b.append("T").append("{");
b.append("Err:").append(getErr()).append(",");
return b.append("}").toString();
}
}
// Code generated by gobind. DO NOT EDIT.
// Java class issue12328.Issue12328 is a proxy for talking to a Go program.
//
// autogenerated by gobind -lang=java issue12328
package issue12328;
import go.Seq;
public abstract class Issue12328 {
static {
Seq.touch(); // for loading the native library
_init();
}
private Issue12328() {} // uninstantiable
// touch is called from other bound packages to initialize this package
public static void touch() {}
private static native void _init();
}

14
bind/testdata/issue12328.java.h.golden vendored Normal file
View file

@ -0,0 +1,14 @@
// Code generated by gobind. DO NOT EDIT.
// JNI function headers for the Go <=> Java bridge.
//
// autogenerated by gobind -lang=java issue12328
#ifndef __Issue12328_H__
#define __Issue12328_H__
#include <jni.h>
extern jclass proxy_class_issue12328_T;
extern jmethodID proxy_class_issue12328_T_cons;
#endif

View file

@ -0,0 +1,11 @@
// Objective-C API for talking to issue12328 Go package.
// gobind -lang=objc issue12328
//
// File is generated by gobind. Do not edit.
#ifndef __GO_issue12328_H__
#define __GO_issue12328_H__
#include <stdint.h>
#include <objc/objc.h>
#endif

Some files were not shown because too many files have changed in this diff Show more