Adding upstream version 0.0~git20250520.a1d9079+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
590ac7ff5f
commit
20149b7f3a
456 changed files with 70406 additions and 0 deletions
59
bind/bind.go
Normal file
59
bind/bind.go
Normal 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
703
bind/bind_test.go
Normal 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
575
bind/gen.go
Normal 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
948
bind/genclasses.go
Normal 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
593
bind/gengo.go
Normal 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
1732
bind/genjava.go
Normal file
File diff suppressed because it is too large
Load diff
1428
bind/genobjc.go
Normal file
1428
bind/genobjc.go
Normal file
File diff suppressed because it is too large
Load diff
754
bind/genobjcw.go
Normal file
754
bind/genobjcw.go
Normal 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
9
bind/implicit.go
Normal 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
157
bind/java/ClassesTest.java
Normal 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);
|
||||
}
|
||||
}
|
15
bind/java/CustomPkgTest.java
Normal file
15
bind/java/CustomPkgTest.java
Normal 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
400
bind/java/Seq.java
Normal 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
162
bind/java/SeqBench.java
Normal 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
602
bind/java/SeqTest.java
Normal 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);
|
||||
}
|
||||
}
|
16
bind/java/context_android.c
Normal file
16
bind/java/context_android.c
Normal 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));
|
||||
}
|
21
bind/java/context_android.go
Normal file
21
bind/java/context_android.go
Normal 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
8
bind/java/doc.go
Normal 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
|
401
bind/java/seq_android.c.support
Normal file
401
bind/java/seq_android.c.support
Normal 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;
|
||||
}
|
98
bind/java/seq_android.go.support
Normal file
98
bind/java/seq_android.go.support
Normal 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
67
bind/java/seq_android.h
Normal 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
256
bind/java/seq_test.go
Normal 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
197
bind/objc/SeqBench.m
Normal 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 it’s 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
22
bind/objc/SeqCustom.m
Normal 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
481
bind/objc/SeqTest.m
Normal 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
98
bind/objc/SeqWrappers.m
Normal 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
6
bind/objc/doc.go
Normal 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
35
bind/objc/ref.h
Normal 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
|
91
bind/objc/seq_darwin.go.support
Normal file
91
bind/objc/seq_darwin.go.support
Normal 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
63
bind/objc/seq_darwin.h
Normal 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__
|
381
bind/objc/seq_darwin.m.support
Normal file
381
bind/objc/seq_darwin.m.support
Normal 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
1009
bind/objc/seq_test.go
Normal file
File diff suppressed because it is too large
Load diff
67
bind/printer.go
Normal file
67
bind/printer.go
Normal 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
52
bind/seq.go.support
Normal 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
153
bind/seq/ref.go
Normal 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
21
bind/seq/seq.go
Normal 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
49
bind/seq/string.go
Normal 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
28
bind/seq/string_test.go
Normal 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
25
bind/testdata/basictypes.go
vendored
Normal 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
73
bind/testdata/basictypes.go.golden
vendored
Normal 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
61
bind/testdata/basictypes.java.c.golden
vendored
Normal 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
37
bind/testdata/basictypes.java.golden
vendored
Normal 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
12
bind/testdata/basictypes.java.h.golden
vendored
Normal 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
|
11
bind/testdata/basictypes.objc.go.h.golden
vendored
Normal file
11
bind/testdata/basictypes.objc.go.h.golden
vendored
Normal 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
32
bind/testdata/basictypes.objc.h.golden
vendored
Normal 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
82
bind/testdata/basictypes.objc.m.golden
vendored
Normal 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
171
bind/testdata/benchmark/benchmark.go
vendored
Normal 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
9
bind/testdata/cgopkg/cgopkg.go
vendored
Normal 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
62
bind/testdata/classes.go
vendored
Normal 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
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
892
bind/testdata/classes.java.c.golden
vendored
Normal 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
155
bind/testdata/classes.java.golden
vendored
Normal 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
103
bind/testdata/classes.java.h.golden
vendored
Normal 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
10
bind/testdata/customprefix.go
vendored
Normal 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() {
|
||||
}
|
23
bind/testdata/customprefix.java.c.golden
vendored
Normal file
23
bind/testdata/customprefix.java.c.golden
vendored
Normal 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
26
bind/testdata/customprefix.java.golden
vendored
Normal 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();
|
||||
}
|
12
bind/testdata/customprefix.java.h.golden
vendored
Normal file
12
bind/testdata/customprefix.java.h.golden
vendored
Normal 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
|
11
bind/testdata/customprefix.objc.go.h.golden
vendored
Normal file
11
bind/testdata/customprefix.objc.go.h.golden
vendored
Normal 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
|
16
bind/testdata/customprefix.objc.h.golden
vendored
Normal file
16
bind/testdata/customprefix.objc.h.golden
vendored
Normal 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
|
18
bind/testdata/customprefix.objc.m.golden
vendored
Normal file
18
bind/testdata/customprefix.objc.m.golden
vendored
Normal 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();
|
||||
}
|
11
bind/testdata/customprefixEX.objc.go.h.golden
vendored
Normal file
11
bind/testdata/customprefixEX.objc.go.h.golden
vendored
Normal 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
|
16
bind/testdata/customprefixEX.objc.h.golden
vendored
Normal file
16
bind/testdata/customprefixEX.objc.h.golden
vendored
Normal 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
|
18
bind/testdata/customprefixEX.objc.m.golden
vendored
Normal file
18
bind/testdata/customprefixEX.objc.m.golden
vendored
Normal 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
59
bind/testdata/doc.go
vendored
Normal 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
190
bind/testdata/doc.go.golden
vendored
Normal 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
194
bind/testdata/doc.java.c.golden
vendored
Normal 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
324
bind/testdata/doc.java.golden
vendored
Normal 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 <HTML>.
|
||||
*/
|
||||
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
23
bind/testdata/doc.java.h.golden
vendored
Normal 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
13
bind/testdata/doc.objc.go.h.golden
vendored
Normal 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
136
bind/testdata/doc.objc.h.golden
vendored
Normal 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
231
bind/testdata/doc.objc.m.golden
vendored
Normal 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
59
bind/testdata/ignore.go
vendored
Normal 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
63
bind/testdata/ignore.go.golden
vendored
Normal 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
75
bind/testdata/ignore.java.c.golden
vendored
Normal 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
135
bind/testdata/ignore.java.golden
vendored
Normal 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
21
bind/testdata/ignore.java.h.golden
vendored
Normal 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
15
bind/testdata/ignore.objc.go.h.golden
vendored
Normal 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
84
bind/testdata/ignore.objc.h.golden
vendored
Normal 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
91
bind/testdata/ignore.objc.m.golden
vendored
Normal 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
69
bind/testdata/interfaces.go
vendored
Normal 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
257
bind/testdata/interfaces.go.golden
vendored
Normal 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
277
bind/testdata/interfaces.java.c.golden
vendored
Normal 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
277
bind/testdata/interfaces.java.golden
vendored
Normal 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
59
bind/testdata/interfaces.java.h.golden
vendored
Normal 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
|
27
bind/testdata/interfaces.objc.go.h.golden
vendored
Normal file
27
bind/testdata/interfaces.objc.go.h.golden
vendored
Normal 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
166
bind/testdata/interfaces.objc.h.golden
vendored
Normal 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
351
bind/testdata/interfaces.objc.m.golden
vendored
Normal 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
14
bind/testdata/issue10788.go
vendored
Normal 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
86
bind/testdata/issue10788.go.golden
vendored
Normal 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
88
bind/testdata/issue10788.java.c.golden
vendored
Normal 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
110
bind/testdata/issue10788.java.golden
vendored
Normal 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
21
bind/testdata/issue10788.java.h.golden
vendored
Normal 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
|
15
bind/testdata/issue10788.objc.go.h.golden
vendored
Normal file
15
bind/testdata/issue10788.objc.go.h.golden
vendored
Normal 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
43
bind/testdata/issue10788.objc.h.golden
vendored
Normal 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
105
bind/testdata/issue10788.objc.m.golden
vendored
Normal 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
9
bind/testdata/issue12328.go
vendored
Normal 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
54
bind/testdata/issue12328.go.golden
vendored
Normal 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
43
bind/testdata/issue12328.java.c.golden
vendored
Normal 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
82
bind/testdata/issue12328.java.golden
vendored
Normal 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
14
bind/testdata/issue12328.java.h.golden
vendored
Normal 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
|
11
bind/testdata/issue12328.objc.go.h.golden
vendored
Normal file
11
bind/testdata/issue12328.objc.go.h.golden
vendored
Normal 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
Loading…
Add table
Add a link
Reference in a new issue