bind,cmd: add generator for ObjC API wrappers
Using the new ObjC type analyzer API, scan the bound packages for references to ObjC classes and protocols and generate Go wrappers for them. This is the second part of the implementation of proposal golang/go#17102. For golang/go#17102 Change-Id: I773db7b0362a7ff526d0a0fd6da5b2fa33301144 Reviewed-on: https://go-review.googlesource.com/29174 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
a82bb3c8ba
commit
6ecf8eedb8
37
bind/bind.go
37
bind/bind.go
|
@ -31,12 +31,6 @@ type (
|
|||
fileType int
|
||||
)
|
||||
|
||||
const (
|
||||
ObjcM = iota
|
||||
ObjcH
|
||||
ObjcGoH
|
||||
)
|
||||
|
||||
// GenGo generates a Go stub to support foreign language APIs.
|
||||
func GenGo(conf *GeneratorConfig) error {
|
||||
buf := new(bytes.Buffer)
|
||||
|
@ -61,34 +55,3 @@ func GenGo(conf *GeneratorConfig) error {
|
|||
_, err = conf.Writer.Write(srcf)
|
||||
return err
|
||||
}
|
||||
|
||||
// GenObjc generates the Objective-C API from a Go package.
|
||||
func GenObjc(conf *GeneratorConfig, prefix string, ft fileType) error {
|
||||
buf := new(bytes.Buffer)
|
||||
g := &objcGen{
|
||||
Generator: &Generator{
|
||||
Printer: &Printer{Buf: buf, IndentEach: []byte("\t")},
|
||||
Fset: conf.Fset,
|
||||
AllPkg: conf.AllPkg,
|
||||
Pkg: conf.Pkg,
|
||||
},
|
||||
prefix: prefix,
|
||||
}
|
||||
g.init()
|
||||
var err error
|
||||
switch ft {
|
||||
case ObjcH:
|
||||
err = g.genH()
|
||||
case ObjcM:
|
||||
err = g.genM()
|
||||
case ObjcGoH:
|
||||
err = g.genGoH()
|
||||
default:
|
||||
panic("invalid fileType")
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = io.Copy(conf.Writer, buf)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
|
||||
"golang.org/x/mobile/internal/importers"
|
||||
"golang.org/x/mobile/internal/importers/java"
|
||||
"golang.org/x/mobile/internal/importers/objc"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -47,14 +48,18 @@ var javaTests = []string{
|
|||
"testdata/classes.go",
|
||||
}
|
||||
|
||||
var objcTests = []string{
|
||||
"testdata/objc.go",
|
||||
}
|
||||
|
||||
var fset = token.NewFileSet()
|
||||
|
||||
func fileRefs(t *testing.T, filename string) *importers.References {
|
||||
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, "Java/")
|
||||
refs, err := importers.AnalyzeFile(f, pkgPrefix)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v", filename, err)
|
||||
}
|
||||
|
@ -119,30 +124,46 @@ func writeTempFile(t *testing.T, name string, contents []byte) string {
|
|||
}
|
||||
|
||||
func TestGenObjc(t *testing.T) {
|
||||
var suffixes = map[fileType]string{
|
||||
ObjcH: ".objc.h.golden",
|
||||
ObjcM: ".objc.m.golden",
|
||||
ObjcGoH: ".objc.go.h.golden",
|
||||
}
|
||||
|
||||
for _, filename := range tests {
|
||||
pkg := typeCheck(t, filename, "")
|
||||
|
||||
for typ, suffix := range suffixes {
|
||||
var buf bytes.Buffer
|
||||
conf := &GeneratorConfig{
|
||||
Writer: &buf,
|
||||
Fset: fset,
|
||||
Pkg: pkg,
|
||||
AllPkg: []*types.Package{pkg},
|
||||
}
|
||||
if err := GenObjc(conf, "", typ); err != nil {
|
||||
var buf bytes.Buffer
|
||||
g := &ObjcGen{
|
||||
Generator: &Generator{
|
||||
Printer: &Printer{Buf: &buf, IndentEach: []byte("\t")},
|
||||
Fset: fset,
|
||||
AllPkg: []*types.Package{pkg},
|
||||
Pkg: pkg,
|
||||
},
|
||||
}
|
||||
g.Init()
|
||||
|
||||
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"+suffix, buf.Bytes())
|
||||
out := writeTempFile(t, "generated"+tc.suffix, buf.Bytes())
|
||||
defer os.Remove(out)
|
||||
golden := filename[:len(filename)-len(".go")] + suffix
|
||||
golden := filename[:len(filename)-len(".go")] + tc.suffix
|
||||
if diffstr := diff(golden, out); diffstr != "" {
|
||||
t.Errorf("%s: does not match Objective-C golden:\n%s", filename, diffstr)
|
||||
if *updateFlag {
|
||||
|
@ -157,6 +178,50 @@ func TestGenObjc(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func genObjcPackages(t *testing.T, dir string, types []*objc.Named, buf *bytes.Buffer) *ObjcWrapper {
|
||||
cg := &ObjcWrapper{
|
||||
Printer: &Printer{
|
||||
IndentEach: []byte("\t"),
|
||||
Buf: buf,
|
||||
},
|
||||
}
|
||||
cg.Init(types)
|
||||
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")
|
||||
buf.Reset()
|
||||
cg.GenPackage(i)
|
||||
if err := ioutil.WriteFile(pkgFile, buf.Bytes(), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
buf.Reset()
|
||||
cg.GenInterfaces()
|
||||
clsFile := filepath.Join(pkgBase, "interfaces.go")
|
||||
if err := ioutil.WriteFile(clsFile, buf.Bytes(), 0600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command(
|
||||
"go",
|
||||
"install",
|
||||
"-pkgdir="+filepath.Join(dir, "pkg", build.Default.GOOS+"_"+build.Default.GOARCH),
|
||||
"ObjC/...",
|
||||
)
|
||||
cmd.Env = append(cmd.Env, "GOPATH="+dir)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Fatalf("failed to go install the generated ObjC wrappers: %v: %s", err, string(out))
|
||||
}
|
||||
return cg
|
||||
}
|
||||
|
||||
func genJavaPackages(t *testing.T, dir string, classes []*java.Class, buf *bytes.Buffer) *ClassGen {
|
||||
cg := &ClassGen{
|
||||
Printer: &Printer{
|
||||
|
@ -207,7 +272,7 @@ func TestGenJava(t *testing.T) {
|
|||
allTests = append(append([]string{}, allTests...), javaTests...)
|
||||
}
|
||||
for _, filename := range allTests {
|
||||
refs := fileRefs(t, filename)
|
||||
refs := fileRefs(t, filename, "Java/")
|
||||
classes, err := java.Import("", "", refs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -294,52 +359,80 @@ func TestGenJava(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestGenGo(t *testing.T) {
|
||||
allTests := tests
|
||||
if java.IsAvailable() {
|
||||
allTests = append(append([]string{}, allTests...), javaTests...)
|
||||
}
|
||||
for _, filename := range allTests {
|
||||
for _, filename := range tests {
|
||||
var buf bytes.Buffer
|
||||
refs := fileRefs(t, 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/")
|
||||
classes, err := java.Import("", "", refs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tmpGopath := ""
|
||||
var cg *ClassGen
|
||||
if len(classes) > 0 {
|
||||
tmpGopath, err = ioutil.TempDir(os.TempDir(), "gomobile-bind-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpGopath)
|
||||
cg = genJavaPackages(t, tmpGopath, classes, &buf)
|
||||
tmpGopath, err := ioutil.TempDir(os.TempDir(), "gomobile-bind-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpGopath)
|
||||
cg := genJavaPackages(t, tmpGopath, classes, &buf)
|
||||
pkg := typeCheck(t, filename, tmpGopath)
|
||||
conf := &GeneratorConfig{
|
||||
Writer: &buf,
|
||||
Fset: fset,
|
||||
Pkg: pkg,
|
||||
AllPkg: []*types.Package{pkg},
|
||||
}
|
||||
if cg != nil {
|
||||
cg.GenGo()
|
||||
}
|
||||
if err := GenGo(conf); err != nil {
|
||||
t.Errorf("%s: %v", filename, err)
|
||||
continue
|
||||
}
|
||||
out := writeTempFile(t, "go", buf.Bytes())
|
||||
defer os.Remove(out)
|
||||
golden := filename + ".golden"
|
||||
if diffstr := diff(golden, out); diffstr != "" {
|
||||
t.Errorf("%s: does not match Java golden:\n%s", filename, diffstr)
|
||||
cg.GenGo()
|
||||
testGenGo(t, filename, &buf, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
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 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 := ioutil.TempDir(os.TempDir(), "gomobile-bind-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tmpGopath)
|
||||
cg := genObjcPackages(t, tmpGopath, types, &buf)
|
||||
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,
|
||||
AllPkg: []*types.Package{pkg},
|
||||
}
|
||||
if err := GenGo(conf); err != nil {
|
||||
t.Errorf("%s: %v", filename, err)
|
||||
return
|
||||
}
|
||||
out := writeTempFile(t, "go", buf.Bytes())
|
||||
defer os.Remove(out)
|
||||
golden := filename + ".golden"
|
||||
if diffstr := diff(golden, 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -350,13 +443,8 @@ func TestCustomPrefix(t *testing.T) {
|
|||
const isHeader = true
|
||||
pkg := typeCheck(t, datafile, "")
|
||||
|
||||
conf := &GeneratorConfig{
|
||||
Fset: fset,
|
||||
Pkg: pkg,
|
||||
AllPkg: []*types.Package{pkg},
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
g := &JavaGen{
|
||||
jg := &JavaGen{
|
||||
JavaPkg: "com.example",
|
||||
Generator: &Generator{
|
||||
Printer: &Printer{Buf: &buf, IndentEach: []byte(" ")},
|
||||
|
@ -365,7 +453,17 @@ func TestCustomPrefix(t *testing.T) {
|
|||
Pkg: pkg,
|
||||
},
|
||||
}
|
||||
g.Init(nil)
|
||||
jg.Init(nil)
|
||||
og := &ObjcGen{
|
||||
Prefix: "EX",
|
||||
Generator: &Generator{
|
||||
Printer: &Printer{Buf: &buf, IndentEach: []byte(" ")},
|
||||
Fset: fset,
|
||||
AllPkg: []*types.Package{pkg},
|
||||
Pkg: pkg,
|
||||
},
|
||||
}
|
||||
og.Init()
|
||||
testCases := []struct {
|
||||
golden string
|
||||
gen func(w io.Writer) error
|
||||
|
@ -374,12 +472,12 @@ func TestCustomPrefix(t *testing.T) {
|
|||
"testdata/customprefix.java.golden",
|
||||
func(w io.Writer) error {
|
||||
buf.Reset()
|
||||
for i := range g.ClassNames() {
|
||||
if err := g.GenClass(i); err != nil {
|
||||
for i := range jg.ClassNames() {
|
||||
if err := jg.GenClass(i); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := g.GenJava(); err != nil {
|
||||
if err := jg.GenJava(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
|
@ -390,7 +488,7 @@ func TestCustomPrefix(t *testing.T) {
|
|||
"testdata/customprefix.java.h.golden",
|
||||
func(w io.Writer) error {
|
||||
buf.Reset()
|
||||
if err := g.GenH(); err != nil {
|
||||
if err := jg.GenH(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
|
@ -401,7 +499,7 @@ func TestCustomPrefix(t *testing.T) {
|
|||
"testdata/customprefix.java.c.golden",
|
||||
func(w io.Writer) error {
|
||||
buf.Reset()
|
||||
if err := g.GenC(); err != nil {
|
||||
if err := jg.GenC(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
|
@ -410,15 +508,36 @@ func TestCustomPrefix(t *testing.T) {
|
|||
},
|
||||
{
|
||||
"testdata/customprefix.objc.go.h.golden",
|
||||
func(w io.Writer) error { conf.Writer = w; return GenObjc(conf, "EX", ObjcGoH) },
|
||||
func(w io.Writer) error {
|
||||
buf.Reset()
|
||||
if err := og.GenGoH(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
"testdata/customprefix.objc.h.golden",
|
||||
func(w io.Writer) error { conf.Writer = w; return GenObjc(conf, "EX", ObjcH) },
|
||||
func(w io.Writer) error {
|
||||
buf.Reset()
|
||||
if err := og.GenH(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
"testdata/customprefix.objc.m.golden",
|
||||
func(w io.Writer) error { conf.Writer = w; return GenObjc(conf, "EX", ObjcM) },
|
||||
func(w io.Writer) error {
|
||||
buf.Reset()
|
||||
if err := og.GenM(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ import (
|
|||
|
||||
// TODO(hyangah): error code/domain propagation
|
||||
|
||||
type objcGen struct {
|
||||
prefix string // prefix arg passed by flag.
|
||||
type ObjcGen struct {
|
||||
Prefix string // prefix arg passed by flag.
|
||||
|
||||
// fields set by init.
|
||||
namePrefix string
|
||||
|
@ -28,23 +28,23 @@ type objcGen struct {
|
|||
*Generator
|
||||
}
|
||||
|
||||
func (g *objcGen) init() {
|
||||
func (g *ObjcGen) Init() {
|
||||
g.Generator.Init()
|
||||
g.namePrefix = g.namePrefixOf(g.Pkg)
|
||||
}
|
||||
|
||||
func (g *objcGen) namePrefixOf(pkg *types.Package) string {
|
||||
func (g *ObjcGen) namePrefixOf(pkg *types.Package) string {
|
||||
if pkg == nil {
|
||||
return "GoUniverse"
|
||||
}
|
||||
p := g.prefix
|
||||
p := g.Prefix
|
||||
if p == "" {
|
||||
p = "Go"
|
||||
}
|
||||
return p + strings.Title(pkg.Name())
|
||||
}
|
||||
|
||||
func (g *objcGen) genGoH() error {
|
||||
func (g *ObjcGen) GenGoH() error {
|
||||
var pkgPath string
|
||||
if g.Pkg != nil {
|
||||
pkgPath = g.Pkg.Path()
|
||||
|
@ -77,7 +77,7 @@ func (g *objcGen) genGoH() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *objcGen) genH() error {
|
||||
func (g *ObjcGen) GenH() error {
|
||||
var pkgPath string
|
||||
if g.Pkg != nil {
|
||||
pkgPath = g.Pkg.Path()
|
||||
|
@ -105,7 +105,7 @@ func (g *objcGen) genH() error {
|
|||
g.Printf("@protocol %s%s;\n", g.namePrefix, i.obj.Name())
|
||||
if i.summary.implementable {
|
||||
g.Printf("@class %s%s;\n", g.namePrefix, i.obj.Name())
|
||||
// Forward declaration for other cases will be handled at the beginning of genM.
|
||||
// Forward declaration for other cases will be handled at the beginning of GenM.
|
||||
}
|
||||
}
|
||||
if len(g.structs) > 0 || len(g.interfaces) > 0 {
|
||||
|
@ -183,15 +183,15 @@ func (g *objcGen) genH() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *objcGen) gobindOpts() string {
|
||||
func (g *ObjcGen) gobindOpts() string {
|
||||
opts := []string{"-lang=objc"}
|
||||
if g.prefix != "" {
|
||||
opts = append(opts, "-prefix="+g.prefix)
|
||||
if g.Prefix != "" {
|
||||
opts = append(opts, "-prefix="+g.Prefix)
|
||||
}
|
||||
return strings.Join(opts, " ")
|
||||
}
|
||||
|
||||
func (g *objcGen) genM() error {
|
||||
func (g *ObjcGen) GenM() error {
|
||||
var pkgPath string
|
||||
if g.Pkg != nil {
|
||||
pkgPath = g.Pkg.Path()
|
||||
|
@ -269,7 +269,7 @@ func (g *objcGen) genM() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (g *objcGen) genVarM(o *types.Var) {
|
||||
func (g *ObjcGen) genVarM(o *types.Var) {
|
||||
if t := o.Type(); !g.isSupported(t) {
|
||||
g.Printf("// skipped variable %s with unsupported type: %T\n\n", o.Name(), t)
|
||||
return
|
||||
|
@ -296,7 +296,7 @@ func (g *objcGen) genVarM(o *types.Var) {
|
|||
g.Printf("}\n\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genConstM(o *types.Const) {
|
||||
func (g *ObjcGen) genConstM(o *types.Const) {
|
||||
if _, ok := o.Type().(*types.Basic); !ok {
|
||||
g.Printf("// skipped const %s with unsupported type: %T\n\n", o.Name(), o)
|
||||
return
|
||||
|
@ -357,7 +357,7 @@ type paramInfo struct {
|
|||
name string
|
||||
}
|
||||
|
||||
func (g *objcGen) funcSummary(obj *types.Func) *funcSummary {
|
||||
func (g *ObjcGen) funcSummary(obj *types.Func) *funcSummary {
|
||||
sig := obj.Type().(*types.Signature)
|
||||
s := &funcSummary{name: obj.Name(), sig: sig}
|
||||
|
||||
|
@ -420,7 +420,7 @@ func (g *objcGen) funcSummary(obj *types.Func) *funcSummary {
|
|||
return s
|
||||
}
|
||||
|
||||
func (s *funcSummary) asFunc(g *objcGen) string {
|
||||
func (s *funcSummary) asFunc(g *ObjcGen) string {
|
||||
var params []string
|
||||
for _, p := range s.params {
|
||||
params = append(params, g.objcType(p.typ)+" "+p.name)
|
||||
|
@ -433,7 +433,7 @@ func (s *funcSummary) asFunc(g *objcGen) string {
|
|||
return fmt.Sprintf("%s %s%s(%s)", s.ret, g.namePrefix, s.name, strings.Join(params, ", "))
|
||||
}
|
||||
|
||||
func (s *funcSummary) asMethod(g *objcGen) string {
|
||||
func (s *funcSummary) asMethod(g *ObjcGen) string {
|
||||
var params []string
|
||||
for i, p := range s.params {
|
||||
var key string
|
||||
|
@ -454,7 +454,7 @@ func (s *funcSummary) asMethod(g *objcGen) string {
|
|||
return fmt.Sprintf("(%s)%s%s", s.ret, objcNameReplacer(lowerFirst(s.name)), strings.Join(params, " "))
|
||||
}
|
||||
|
||||
func (s *funcSummary) callMethod(g *objcGen) string {
|
||||
func (s *funcSummary) callMethod(g *ObjcGen) string {
|
||||
var params []string
|
||||
for i, p := range s.params {
|
||||
var key string
|
||||
|
@ -479,11 +479,11 @@ func (s *funcSummary) returnsVal() bool {
|
|||
return len(s.retParams) == 1 && !isErrorType(s.retParams[0].typ)
|
||||
}
|
||||
|
||||
func (g *objcGen) paramName(params *types.Tuple, pos int) string {
|
||||
func (g *ObjcGen) paramName(params *types.Tuple, pos int) string {
|
||||
return basicParamName(params, pos)
|
||||
}
|
||||
|
||||
func (g *objcGen) genFuncH(obj *types.Func) {
|
||||
func (g *ObjcGen) genFuncH(obj *types.Func) {
|
||||
if !g.isSigSupported(obj.Type()) {
|
||||
g.Printf("// skipped function %s with unsupported parameter or return types\n\n", obj.Name())
|
||||
return
|
||||
|
@ -493,7 +493,7 @@ func (g *objcGen) genFuncH(obj *types.Func) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *objcGen) genFuncM(obj *types.Func) {
|
||||
func (g *ObjcGen) genFuncM(obj *types.Func) {
|
||||
s := g.funcSummary(obj)
|
||||
if s == nil {
|
||||
return
|
||||
|
@ -505,7 +505,7 @@ func (g *objcGen) genFuncM(obj *types.Func) {
|
|||
g.Printf("}\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genGetter(oName string, f *types.Var) {
|
||||
func (g *ObjcGen) genGetter(oName string, f *types.Var) {
|
||||
t := f.Type()
|
||||
g.Printf("- (%s)%s {\n", g.objcType(t), objcNameReplacer(lowerFirst(f.Name())))
|
||||
g.Indent()
|
||||
|
@ -518,7 +518,7 @@ func (g *objcGen) genGetter(oName string, f *types.Var) {
|
|||
g.Printf("}\n\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genSetter(oName string, f *types.Var) {
|
||||
func (g *ObjcGen) genSetter(oName string, f *types.Var) {
|
||||
t := f.Type()
|
||||
|
||||
g.Printf("- (void)set%s:(%s)v {\n", f.Name(), g.objcType(t))
|
||||
|
@ -531,7 +531,7 @@ func (g *objcGen) genSetter(oName string, f *types.Var) {
|
|||
g.Printf("}\n\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genWrite(varName string, t types.Type, mode varMode) {
|
||||
func (g *ObjcGen) genWrite(varName string, t types.Type, mode varMode) {
|
||||
switch t := t.(type) {
|
||||
case *types.Basic:
|
||||
switch t.Kind() {
|
||||
|
@ -566,7 +566,7 @@ func (g *objcGen) genWrite(varName string, t types.Type, mode varMode) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *objcGen) genRefWrite(varName string, t types.Type) {
|
||||
func (g *ObjcGen) genRefWrite(varName string, t types.Type) {
|
||||
g.Printf("int32_t _%s;\n", varName)
|
||||
g.Printf("if ([(id<NSObject>)(%s) isKindOfClass:[%s class]]) {\n", varName, g.refTypeBase(t))
|
||||
g.Indent()
|
||||
|
@ -580,7 +580,7 @@ func (g *objcGen) genRefWrite(varName string, t types.Type) {
|
|||
g.Printf("}\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genRefRead(toName, fromName string, t types.Type) {
|
||||
func (g *ObjcGen) genRefRead(toName, fromName string, t types.Type) {
|
||||
ptype := g.refTypeBase(t)
|
||||
g.Printf("%s* %s = nil;\n", ptype, toName)
|
||||
g.Printf("GoSeqRef* %s_ref = go_seq_from_refnum(%s);\n", toName, fromName)
|
||||
|
@ -592,7 +592,7 @@ func (g *objcGen) genRefRead(toName, fromName string, t types.Type) {
|
|||
g.Printf("}\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genRead(toName, fromName string, t types.Type, mode varMode) {
|
||||
func (g *ObjcGen) genRead(toName, fromName string, t types.Type, mode varMode) {
|
||||
switch t := t.(type) {
|
||||
case *types.Basic:
|
||||
switch t.Kind() {
|
||||
|
@ -634,7 +634,7 @@ func (g *objcGen) genRead(toName, fromName string, t types.Type, mode varMode) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *objcGen) genFunc(s *funcSummary, objName string) {
|
||||
func (g *ObjcGen) genFunc(s *funcSummary, objName string) {
|
||||
if objName != "" {
|
||||
g.Printf("int32_t refnum = go_seq_go_to_refnum(self._ref);\n")
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ func (g *objcGen) genFunc(s *funcSummary, objName string) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *objcGen) genInterfaceInterface(obj *types.TypeName, summary ifaceSummary, isProtocol bool) {
|
||||
func (g *ObjcGen) genInterfaceInterface(obj *types.TypeName, summary ifaceSummary, isProtocol bool) {
|
||||
g.Printf("@interface %[1]s%[2]s : ", g.namePrefix, obj.Name())
|
||||
if isErrorType(obj.Type()) {
|
||||
g.Printf("NSError")
|
||||
|
@ -718,7 +718,7 @@ func (g *objcGen) genInterfaceInterface(obj *types.TypeName, summary ifaceSummar
|
|||
g.Printf("@end\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genInterfaceH(obj *types.TypeName, t *types.Interface) {
|
||||
func (g *ObjcGen) genInterfaceH(obj *types.TypeName, t *types.Interface) {
|
||||
summary := makeIfaceSummary(t)
|
||||
if !summary.implementable {
|
||||
g.genInterfaceInterface(obj, summary, false)
|
||||
|
@ -736,7 +736,7 @@ func (g *objcGen) genInterfaceH(obj *types.TypeName, t *types.Interface) {
|
|||
g.Printf("@end\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genInterfaceM(obj *types.TypeName, t *types.Interface) bool {
|
||||
func (g *ObjcGen) genInterfaceM(obj *types.TypeName, t *types.Interface) bool {
|
||||
summary := makeIfaceSummary(t)
|
||||
|
||||
// @implementation Interface -- similar to what genStructM does.
|
||||
|
@ -777,7 +777,7 @@ func (g *objcGen) genInterfaceM(obj *types.TypeName, t *types.Interface) bool {
|
|||
return summary.implementable
|
||||
}
|
||||
|
||||
func (g *objcGen) genInterfaceMethodProxy(obj *types.TypeName, m *types.Func) {
|
||||
func (g *ObjcGen) genInterfaceMethodProxy(obj *types.TypeName, m *types.Func) {
|
||||
oName := obj.Name()
|
||||
s := g.funcSummary(m)
|
||||
g.genInterfaceMethodSignature(m, oName, false, g.paramName)
|
||||
|
@ -855,7 +855,7 @@ func (g *objcGen) genInterfaceMethodProxy(obj *types.TypeName, m *types.Func) {
|
|||
}
|
||||
|
||||
// genRelease cleans up arguments that weren't copied in genWrite.
|
||||
func (g *objcGen) genRelease(varName string, t types.Type, mode varMode) {
|
||||
func (g *ObjcGen) genRelease(varName string, t types.Type, mode varMode) {
|
||||
switch t := t.(type) {
|
||||
case *types.Slice:
|
||||
switch e := t.Elem().(type) {
|
||||
|
@ -874,7 +874,7 @@ func (g *objcGen) genRelease(varName string, t types.Type, mode varMode) {
|
|||
}
|
||||
}
|
||||
|
||||
func (g *objcGen) genStructH(obj *types.TypeName, t *types.Struct) {
|
||||
func (g *ObjcGen) genStructH(obj *types.TypeName, t *types.Struct) {
|
||||
g.Printf("@interface %s%s : NSObject {\n", g.namePrefix, obj.Name())
|
||||
g.Printf("}\n")
|
||||
g.Printf("@property(strong, readonly) id _ref;\n")
|
||||
|
@ -904,7 +904,7 @@ func (g *objcGen) genStructH(obj *types.TypeName, t *types.Struct) {
|
|||
g.Printf("@end\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) genStructM(obj *types.TypeName, t *types.Struct) {
|
||||
func (g *ObjcGen) genStructM(obj *types.TypeName, t *types.Struct) {
|
||||
fields := exportedFields(t)
|
||||
methods := exportedMethodSet(types.NewPointer(obj.Type()))
|
||||
|
||||
|
@ -943,11 +943,11 @@ func (g *objcGen) genStructM(obj *types.TypeName, t *types.Struct) {
|
|||
g.Printf("@end\n")
|
||||
}
|
||||
|
||||
func (g *objcGen) errorf(format string, args ...interface{}) {
|
||||
func (g *ObjcGen) errorf(format string, args ...interface{}) {
|
||||
g.err = append(g.err, fmt.Errorf(format, args...))
|
||||
}
|
||||
|
||||
func (g *objcGen) refTypeBase(typ types.Type) string {
|
||||
func (g *ObjcGen) refTypeBase(typ types.Type) string {
|
||||
switch typ := typ.(type) {
|
||||
case *types.Pointer:
|
||||
if _, ok := typ.Elem().(*types.Named); ok {
|
||||
|
@ -967,14 +967,14 @@ func (g *objcGen) refTypeBase(typ types.Type) string {
|
|||
return g.objcType(typ)
|
||||
}
|
||||
|
||||
func (g *objcGen) objcFieldType(t types.Type) string {
|
||||
func (g *ObjcGen) objcFieldType(t types.Type) string {
|
||||
if isErrorType(t) {
|
||||
return "NSError*"
|
||||
}
|
||||
return g.objcType(t)
|
||||
}
|
||||
|
||||
func (g *objcGen) objcType(typ types.Type) string {
|
||||
func (g *ObjcGen) objcType(typ types.Type) string {
|
||||
if isErrorType(typ) {
|
||||
return "NSError*"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,735 @@
|
|||
// 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/filepath"
|
||||
"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
|
||||
}
|
||||
)
|
||||
|
||||
func (g *ObjcWrapper) Init(types []*objc.Named) {
|
||||
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 _, 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("//File is generated by gobind. Do not edit.\n\n")
|
||||
// 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 !n.Protocol {
|
||||
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 = [%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.Float, objc.Double, objc.Class, objc.Protocol:
|
||||
default:
|
||||
// If support struct 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("id<GoUniverseerror> _%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("//File is generated by gobind. Do not edit.\n\n")
|
||||
g.Printf("#include \"seq.h\"\n\n")
|
||||
for _, m := range g.modules {
|
||||
g.Printf("@import %s;\n", m)
|
||||
}
|
||||
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 !n.Protocol {
|
||||
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(g.cType(ret))
|
||||
case returnsErr:
|
||||
g.Printf("int")
|
||||
default:
|
||||
g.Printf("void")
|
||||
}
|
||||
g.Printf(" ")
|
||||
g.Printf(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("// File is generated by gobind. Do not edit.\n\n")
|
||||
g.Printf("package gomobile_bind\n\n")
|
||||
g.Printf("// #cgo CFLAGS: -fobjc-arc -fmodules -fblocks\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 !n.Protocol {
|
||||
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.")
|
||||
g.Printf(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.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.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, 0)\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.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.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, 1)\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("//File is generated by gobind. Do not edit.\n\n")
|
||||
g.Printf("package %s\n\n", filepath.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("//File is generated by gobind. Do not edit.\n\n")
|
||||
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(f.GoName)
|
||||
g.genFuncDecl(true, f)
|
||||
g.Printf("\n")
|
||||
}
|
||||
if !n.Protocol {
|
||||
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.Float:
|
||||
return "float32"
|
||||
case objc.Double:
|
||||
return "float64"
|
||||
case objc.Protocol, objc.Class:
|
||||
var n *objc.Named
|
||||
n = g.lookupImported(t)
|
||||
if n == nil {
|
||||
return "interface{}"
|
||||
}
|
||||
name := n.Module + "_" + n.GoName
|
||||
if !local {
|
||||
name = "ObjC." + name
|
||||
}
|
||||
return name
|
||||
default:
|
||||
panic("invalid kind")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
// 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.
|
||||
|
||||
// +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 {
|
||||
GoObjcpkgFunc();
|
||||
}
|
||||
|
||||
- (void)testMethod {
|
||||
GoObjcpkgMethod();
|
||||
}
|
||||
|
||||
- (void)testNew {
|
||||
GoObjcpkgNew();
|
||||
}
|
||||
|
||||
- (void)testError {
|
||||
GoObjcpkgError();
|
||||
}
|
||||
@end
|
|
@ -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
|
|
@ -51,6 +51,12 @@ func TestObjcSeqBench(t *testing.T) {
|
|||
runTest(t, []string{"golang.org/x/mobile/bind/benchmark"}, "xcodebench", "SeqBench.m", true)
|
||||
}
|
||||
|
||||
// TestObjcSeqWrappers runs ObjC test SeqWrappers.m.
|
||||
// This requires the xcode command lines tools.
|
||||
func TestObjcSeqWrappers(t *testing.T) {
|
||||
runTest(t, []string{"golang.org/x/mobile/bind/testpkg/objcpkg"}, "xcodewrappers", "SeqWrappers.m", false)
|
||||
}
|
||||
|
||||
func runTest(t *testing.T, pkgNames []string, project, testfile string, dumpOutput bool) {
|
||||
if _, err := run("which xcodebuild"); err != nil {
|
||||
t.Skip("command xcodebuild not found, skipping")
|
||||
|
|
|
@ -0,0 +1,297 @@
|
|||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
641ECD4C1C8C20D000971615 /* SeqWrappers.m in Sources */ = {isa = PBXBuildFile; fileRef = 641ECD4B1C8C20D000971615 /* SeqWrappers.m */; };
|
||||
641ECD551C8C380400971615 /* Objcpkg.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 641ECD4D1C8C20FD00971615 /* Objcpkg.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
641ECD3D1C8C20BB00971615 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 641ECD1B1C8C20BB00971615 /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 641ECD221C8C20BB00971615;
|
||||
remoteInfo = xcodewrappers;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
641ECD371C8C20BB00971615 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
641ECD421C8C20BB00971615 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
641ECD4B1C8C20D000971615 /* SeqWrappers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SeqWrappers.m; path = ../../SeqWrappers.m; sourceTree = "<group>"; };
|
||||
641ECD4D1C8C20FD00971615 /* Objcpkg.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Objcpkg.framework; sourceTree = SOURCE_ROOT; };
|
||||
641ECD4F1C8C356C00971615 /* xcodewrappersTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = xcodewrappersTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
641ECD391C8C20BB00971615 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
641ECD551C8C380400971615 /* Objcpkg.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
641ECD1A1C8C20BB00971615 = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
641ECD251C8C20BB00971615 /* xcodewrappers */,
|
||||
641ECD3F1C8C20BB00971615 /* xcodewrappersTests */,
|
||||
641ECD501C8C356C00971615 /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
641ECD251C8C20BB00971615 /* xcodewrappers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
641ECD371C8C20BB00971615 /* Info.plist */,
|
||||
);
|
||||
path = xcodewrappers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
641ECD3F1C8C20BB00971615 /* xcodewrappersTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
641ECD4D1C8C20FD00971615 /* Objcpkg.framework */,
|
||||
641ECD4B1C8C20D000971615 /* SeqWrappers.m */,
|
||||
641ECD421C8C20BB00971615 /* Info.plist */,
|
||||
);
|
||||
path = xcodewrappersTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
641ECD501C8C356C00971615 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
641ECD4F1C8C356C00971615 /* xcodewrappersTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
641ECD3B1C8C20BB00971615 /* xcodewrappersTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 641ECD481C8C20BB00971615 /* Build configuration list for PBXNativeTarget "xcodewrappersTests" */;
|
||||
buildPhases = (
|
||||
641ECD391C8C20BB00971615 /* Frameworks */,
|
||||
641ECD381C8C20BB00971615 /* Sources */,
|
||||
641ECD3A1C8C20BB00971615 /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
641ECD3E1C8C20BB00971615 /* PBXTargetDependency */,
|
||||
);
|
||||
name = xcodewrappersTests;
|
||||
productName = xcodewrappersTests;
|
||||
productReference = 641ECD4F1C8C356C00971615 /* xcodewrappersTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
641ECD1B1C8C20BB00971615 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0720;
|
||||
ORGANIZATIONNAME = golang.org;
|
||||
TargetAttributes = {
|
||||
641ECD3B1C8C20BB00971615 = {
|
||||
CreatedOnToolsVersion = 7.2.1;
|
||||
TestTargetID = 641ECD221C8C20BB00971615;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 641ECD1E1C8C20BB00971615 /* Build configuration list for PBXProject "xcodewrappers" */;
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
Base,
|
||||
);
|
||||
mainGroup = 641ECD1A1C8C20BB00971615;
|
||||
productRefGroup = 641ECD501C8C356C00971615 /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
641ECD3B1C8C20BB00971615 /* xcodewrappersTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
641ECD3A1C8C20BB00971615 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
641ECD381C8C20BB00971615 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
641ECD4C1C8C20D000971615 /* SeqWrappers.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
641ECD3E1C8C20BB00971615 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
targetProxy = 641ECD3D1C8C20BB00971615 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
641ECD431C8C20BB00971615 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
641ECD441C8C20BB00971615 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_TREAT_WARNINGS_AS_ERRORS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.2;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
641ECD511C8C362D00971615 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = NO;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
PRODUCT_NAME = xcodewrappersTests;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
641ECD521C8C362D00971615 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)",
|
||||
);
|
||||
PRODUCT_NAME = xcodewrappersTests;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
641ECD1E1C8C20BB00971615 /* Build configuration list for PBXProject "xcodewrappers" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
641ECD431C8C20BB00971615 /* Debug */,
|
||||
641ECD441C8C20BB00971615 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
641ECD481C8C20BB00971615 /* Build configuration list for PBXNativeTarget "xcodewrappersTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
641ECD511C8C362D00971615 /* Debug */,
|
||||
641ECD521C8C362D00971615 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 641ECD1B1C8C20BB00971615 /* Project object */;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "0720"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "641ECD221C8C20BB00971615"
|
||||
BuildableName = "xcodewrappers.app"
|
||||
BlueprintName = "xcodewrappers"
|
||||
ReferencedContainer = "container:xcodewrappers.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
<TestableReference
|
||||
skipped = "NO">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "641ECD3B1C8C20BB00971615"
|
||||
BuildableName = "xcodewrappersTests.xctest"
|
||||
BlueprintName = "xcodewrappersTests"
|
||||
ReferencedContainer = "container:xcodewrappers.xcodeproj">
|
||||
</BuildableReference>
|
||||
</TestableReference>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "641ECD221C8C20BB00971615"
|
||||
BuildableName = "xcodewrappers.app"
|
||||
BlueprintName = "xcodewrappers"
|
||||
ReferencedContainer = "container:xcodewrappers.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "NO"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "641ECD221C8C20BB00971615"
|
||||
BuildableName = "xcodewrappers.app"
|
||||
BlueprintName = "xcodewrappers"
|
||||
ReferencedContainer = "container:xcodewrappers.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "641ECD221C8C20BB00971615"
|
||||
BuildableName = "xcodewrappers.app"
|
||||
BlueprintName = "xcodewrappers"
|
||||
ReferencedContainer = "container:xcodewrappers.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
|
@ -10,9 +10,9 @@
|
|||
|
||||
|
||||
void EXCustomprefixF() {
|
||||
proxycustomprefix__F();
|
||||
proxycustomprefix__F();
|
||||
}
|
||||
|
||||
__attribute__((constructor)) static void init() {
|
||||
init_seq();
|
||||
init_seq();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// 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 objc
|
||||
|
||||
import (
|
||||
"ObjC/Foundation"
|
||||
)
|
||||
|
||||
type (
|
||||
S Foundation.NSString
|
||||
D Foundation.NSDate
|
||||
O Foundation.NSObjectC
|
||||
)
|
|
@ -0,0 +1,119 @@
|
|||
//File is generated by gobind. Do not edit.
|
||||
|
||||
package ObjC
|
||||
|
||||
// Used to silence this package not used errors
|
||||
const Dummy = 0
|
||||
|
||||
type Foundation_NSString interface {
|
||||
Super() Foundation_NSString
|
||||
}
|
||||
|
||||
type Foundation_NSDate interface {
|
||||
Super() Foundation_NSDate
|
||||
}
|
||||
|
||||
type Foundation_NSObjectC interface {
|
||||
Super() Foundation_NSObjectC
|
||||
}
|
||||
|
||||
// File is generated by gobind. Do not edit.
|
||||
|
||||
package gomobile_bind
|
||||
|
||||
// #cgo CFLAGS: -fobjc-arc -fmodules -fblocks
|
||||
// #include "interfaces.h"
|
||||
import "C"
|
||||
|
||||
import "ObjC"
|
||||
import _seq "golang.org/x/mobile/bind/seq"
|
||||
|
||||
type proxy interface { Bind_proxy_refnum__() int32 }
|
||||
|
||||
// Suppress unused package error
|
||||
|
||||
var _ = _seq.FromRefNum
|
||||
const _ = ObjC.Dummy
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
type proxy_class_NSString _seq.Ref
|
||||
|
||||
func (p *proxy_class_NSString) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
|
||||
|
||||
func (p *proxy_class_NSString) Super() ObjC.Foundation_NSString {
|
||||
return &super_NSString{p}
|
||||
}
|
||||
|
||||
type super_NSString struct {*proxy_class_NSString}
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
type proxy_class_NSDate _seq.Ref
|
||||
|
||||
func (p *proxy_class_NSDate) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
|
||||
|
||||
func (p *proxy_class_NSDate) Super() ObjC.Foundation_NSDate {
|
||||
return &super_NSDate{p}
|
||||
}
|
||||
|
||||
type super_NSDate struct {*proxy_class_NSDate}
|
||||
|
||||
func init() {
|
||||
}
|
||||
|
||||
type proxy_class_NSObjectC _seq.Ref
|
||||
|
||||
func (p *proxy_class_NSObjectC) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
|
||||
|
||||
func (p *proxy_class_NSObjectC) Super() ObjC.Foundation_NSObjectC {
|
||||
return &super_NSObjectC{p}
|
||||
}
|
||||
|
||||
type super_NSObjectC struct {*proxy_class_NSObjectC}
|
||||
|
||||
// Package gomobile_bind is an autogenerated binder stub for package objc.
|
||||
// gobind -lang=go objc
|
||||
//
|
||||
// File is generated by gobind. Do not edit.
|
||||
package gomobile_bind
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "seq.h"
|
||||
#include "objc.h"
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
_seq "golang.org/x/mobile/bind/seq"
|
||||
)
|
||||
|
||||
// suppress the error if seq ends up unused
|
||||
var _ = _seq.FromRefNum
|
||||
|
||||
// skipped method D.Super with unsupported parameter or return types
|
||||
|
||||
type proxyobjc_D _seq.Ref
|
||||
|
||||
func (p *proxyobjc_D) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
|
||||
|
||||
// skipped method D.Super with unsupported parameter or result types
|
||||
// skipped method O.Super with unsupported parameter or return types
|
||||
|
||||
type proxyobjc_O _seq.Ref
|
||||
|
||||
func (p *proxyobjc_O) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
|
||||
|
||||
// skipped method O.Super with unsupported parameter or result types
|
||||
// skipped method S.Super with unsupported parameter or return types
|
||||
|
||||
type proxyobjc_S _seq.Ref
|
||||
|
||||
func (p *proxyobjc_S) Bind_proxy_refnum__() int32 { return (*_seq.Ref)(p).Bind_IncNum() }
|
||||
|
||||
// skipped method S.Super with unsupported parameter or result types
|
|
@ -0,0 +1,47 @@
|
|||
// 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 objcpkg
|
||||
|
||||
import (
|
||||
"ObjC/Foundation/NSDate"
|
||||
"ObjC/Foundation/NSString"
|
||||
"ObjC/QuartzCore/CAMediaTimingFunction"
|
||||
)
|
||||
|
||||
func Func() {
|
||||
NSDate.Date()
|
||||
CAMediaTimingFunction.FunctionWithControlPoints(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
func Method() string {
|
||||
d := NSDate.Date()
|
||||
return d.Description()
|
||||
}
|
||||
|
||||
func New() {
|
||||
NSDate.New()
|
||||
CAMediaTimingFunction.NewWithControlPoints(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
func Error() {
|
||||
str, err := NSString.StringWithContentsOfFileEncodingError("<non-existent>", 0)
|
||||
if err == nil {
|
||||
panic("no error from stringWithContentsOfFile")
|
||||
}
|
||||
// Assert err is an error
|
||||
err = err.(error)
|
||||
if str != "" {
|
||||
panic("non-empty string from stringWithContentsOfFile")
|
||||
}
|
||||
str, err = NSString.NewWithContentsOfFileEncodingError("<non-existent>", 0)
|
||||
if err == nil {
|
||||
panic("no error from stringWithContentsOfFile")
|
||||
}
|
||||
// Assert err is an error
|
||||
err = err.(error)
|
||||
if str != "" {
|
||||
panic("non-empty string from initWithContentsOfFile")
|
||||
}
|
||||
}
|
|
@ -109,18 +109,31 @@ func genPkg(p *types.Package, allPkg []*types.Package, classes []*java.Class) {
|
|||
} else {
|
||||
gohname = "GoUniverse.h"
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
g := &bind.ObjcGen{
|
||||
Generator: &bind.Generator{
|
||||
Printer: &bind.Printer{Buf: &buf, IndentEach: []byte("\t")},
|
||||
Fset: conf.Fset,
|
||||
AllPkg: conf.AllPkg,
|
||||
Pkg: conf.Pkg,
|
||||
},
|
||||
Prefix: *prefix,
|
||||
}
|
||||
g.Init()
|
||||
|
||||
w, closer := writer(gohname)
|
||||
conf.Writer = w
|
||||
processErr(bind.GenObjc(conf, *prefix, bind.ObjcGoH))
|
||||
processErr(g.GenGoH())
|
||||
io.Copy(w, &buf)
|
||||
closer()
|
||||
hname := fname[:len(fname)-2] + ".h"
|
||||
w, closer = writer(hname)
|
||||
conf.Writer = w
|
||||
processErr(bind.GenObjc(conf, *prefix, bind.ObjcH))
|
||||
processErr(g.GenH())
|
||||
io.Copy(w, &buf)
|
||||
closer()
|
||||
w, closer = writer(fname)
|
||||
conf.Writer = w
|
||||
processErr(bind.GenObjc(conf, *prefix, bind.ObjcM))
|
||||
processErr(g.GenM())
|
||||
io.Copy(w, &buf)
|
||||
closer()
|
||||
default:
|
||||
errorf("unknown target language: %q", *lang)
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"golang.org/x/mobile/bind"
|
||||
"golang.org/x/mobile/internal/importers"
|
||||
"golang.org/x/mobile/internal/importers/java"
|
||||
"golang.org/x/mobile/internal/importers/objc"
|
||||
)
|
||||
|
||||
// ctx, pkg, tmpdir in build.go
|
||||
|
@ -180,10 +181,13 @@ func (b *binder) GenObjcSupport(outdir string) error {
|
|||
if err := copyFile(filepath.Join(outdir, "seq_darwin.go"), filepath.Join(objcPkg.Dir, "seq_darwin.go.support")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := copyFile(filepath.Join(outdir, "ref.h"), filepath.Join(objcPkg.Dir, "ref.h")); err != nil {
|
||||
return err
|
||||
}
|
||||
return copyFile(filepath.Join(outdir, "seq.h"), filepath.Join(objcPkg.Dir, "seq.h"))
|
||||
}
|
||||
|
||||
func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir string) (string, error) {
|
||||
func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir string, wrappers []*objc.Named) (string, error) {
|
||||
const bindPrefixDefault = "Go"
|
||||
if bindPrefix == "" || pkg == nil {
|
||||
bindPrefix = bindPrefixDefault
|
||||
|
@ -206,11 +210,18 @@ func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir str
|
|||
hfile := filepath.Join(outdir, fileBase+".h")
|
||||
gohfile := filepath.Join(outdir, pkgName+".h")
|
||||
|
||||
conf := &bind.GeneratorConfig{
|
||||
Fset: b.fset,
|
||||
Pkg: pkg,
|
||||
AllPkg: allPkg,
|
||||
var buf bytes.Buffer
|
||||
g := &bind.ObjcGen{
|
||||
Generator: &bind.Generator{
|
||||
Printer: &bind.Printer{Buf: &buf, IndentEach: []byte("\t")},
|
||||
Fset: b.fset,
|
||||
AllPkg: allPkg,
|
||||
Pkg: pkg,
|
||||
},
|
||||
Prefix: bindPrefix,
|
||||
}
|
||||
g.Init()
|
||||
|
||||
generate := func(w io.Writer) error {
|
||||
if buildX {
|
||||
printcmd("gobind %s -outdir=%s %s", bindOption, outdir, pkgPath)
|
||||
|
@ -218,8 +229,12 @@ func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir str
|
|||
if buildN {
|
||||
return nil
|
||||
}
|
||||
conf.Writer = w
|
||||
return bind.GenObjc(conf, bindPrefix, bind.ObjcM)
|
||||
buf.Reset()
|
||||
if err := g.GenM(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(mfile, generate); err != nil {
|
||||
return "", err
|
||||
|
@ -228,8 +243,12 @@ func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir str
|
|||
if buildN {
|
||||
return nil
|
||||
}
|
||||
conf.Writer = w
|
||||
return bind.GenObjc(conf, bindPrefix, bind.ObjcH)
|
||||
buf.Reset()
|
||||
if err := g.GenH(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(hfile, generate); err != nil {
|
||||
return "", err
|
||||
|
@ -238,8 +257,12 @@ func (b *binder) GenObjc(pkg *types.Package, allPkg []*types.Package, outdir str
|
|||
if buildN {
|
||||
return nil
|
||||
}
|
||||
conf.Writer = w
|
||||
return bind.GenObjc(conf, bindPrefix, bind.ObjcGoH)
|
||||
buf.Reset()
|
||||
if err := g.GenGoH(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(gohfile, generate); err != nil {
|
||||
return "", err
|
||||
|
@ -273,6 +296,93 @@ func bootClasspath() (string, error) {
|
|||
return filepath.Join(apiPath, "android.jar"), nil
|
||||
}
|
||||
|
||||
func GenObjcWrappers(pkgs []*build.Package, srcDir, pkgGen string) ([]*objc.Named, error) {
|
||||
refs, err := importers.AnalyzePackages(pkgs, "ObjC/")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
types, err := objc.Import(refs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
g := &bind.ObjcWrapper{
|
||||
Printer: &bind.Printer{
|
||||
IndentEach: []byte("\t"),
|
||||
Buf: &buf,
|
||||
},
|
||||
}
|
||||
g.Init(types)
|
||||
for i, name := range g.Packages() {
|
||||
pkgDir := filepath.Join(pkgGen, "src", "ObjC", name)
|
||||
if err := os.MkdirAll(pkgDir, 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkgFile := filepath.Join(pkgDir, "package.go")
|
||||
generate := func(w io.Writer) error {
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
buf.Reset()
|
||||
g.GenPackage(i)
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(pkgFile, generate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create the ObjC wrapper package %s: %v", name, err)
|
||||
}
|
||||
}
|
||||
generate := func(w io.Writer) error {
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
buf.Reset()
|
||||
g.GenGo()
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(filepath.Join(srcDir, "interfaces.go"), generate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create the ObjC wrapper Go file: %v", err)
|
||||
}
|
||||
generate = func(w io.Writer) error {
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
buf.Reset()
|
||||
g.GenInterfaces()
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(filepath.Join(pkgGen, "src", "ObjC", "interfaces.go"), generate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create the ObjC wrapper Go file: %v", err)
|
||||
}
|
||||
generate = func(w io.Writer) error {
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
buf.Reset()
|
||||
g.GenH()
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(filepath.Join(srcDir, "interfaces.h"), generate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create the ObjC wrapper header file: %v", err)
|
||||
}
|
||||
generate = func(w io.Writer) error {
|
||||
if buildN {
|
||||
return nil
|
||||
}
|
||||
buf.Reset()
|
||||
g.GenM()
|
||||
_, err := io.Copy(w, &buf)
|
||||
return err
|
||||
}
|
||||
if err := writeFile(filepath.Join(srcDir, "interfaces.m"), generate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create the Java classes ObjC file: %v", err)
|
||||
}
|
||||
return types, nil
|
||||
}
|
||||
|
||||
func GenClasses(pkgs []*build.Package, srcDir, jpkgSrc string) ([]*java.Class, error) {
|
||||
refs, err := importers.AnalyzePackages(pkgs, "Java/")
|
||||
if err != nil {
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -16,7 +17,16 @@ import (
|
|||
)
|
||||
|
||||
func goIOSBind(pkgs []*build.Package) error {
|
||||
typesPkgs, err := loadExportData(pkgs, darwinArmEnv)
|
||||
srcDir := filepath.Join(tmpdir, "src", "gomobile_bind")
|
||||
genDir := filepath.Join(tmpdir, "gen")
|
||||
wrappers, err := GenObjcWrappers(pkgs, srcDir, genDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
env := darwinArmEnv
|
||||
gopath := fmt.Sprintf("GOPATH=%s%c%s", genDir, filepath.ListSeparator, os.Getenv("GOPATH"))
|
||||
env = append(env, gopath)
|
||||
typesPkgs, err := loadExportData(pkgs, env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -35,7 +45,6 @@ func goIOSBind(pkgs []*build.Package) error {
|
|||
buildO = title + ".framework"
|
||||
}
|
||||
|
||||
srcDir := filepath.Join(tmpdir, "src", "gomobile_bind")
|
||||
for _, pkg := range binder.pkgs {
|
||||
if err := binder.GenGo(pkg, binder.pkgs, srcDir); err != nil {
|
||||
return err
|
||||
|
@ -56,11 +65,11 @@ func goIOSBind(pkgs []*build.Package) error {
|
|||
|
||||
fileBases := make([]string, len(typesPkgs)+1)
|
||||
for i, pkg := range binder.pkgs {
|
||||
if fileBases[i], err = binder.GenObjc(pkg, binder.pkgs, srcDir); err != nil {
|
||||
if fileBases[i], err = binder.GenObjc(pkg, binder.pkgs, srcDir, wrappers); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if fileBases[len(fileBases)-1], err = binder.GenObjc(nil, binder.pkgs, srcDir); err != nil {
|
||||
if fileBases[len(fileBases)-1], err = binder.GenObjc(nil, binder.pkgs, srcDir, wrappers); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := binder.GenObjcSupport(srcDir); err != nil {
|
||||
|
@ -73,6 +82,7 @@ func goIOSBind(pkgs []*build.Package) error {
|
|||
cmd := exec.Command("xcrun", "lipo", "-create")
|
||||
|
||||
for _, env := range [][]string{darwinArmEnv, darwinArm64Env, darwinAmd64Env} {
|
||||
env = append(env, gopath)
|
||||
arch := archClang(getenv(env, "GOARCH"))
|
||||
path, err := goIOSBindArchive(name, mainFile, env, fileBases)
|
||||
if err != nil {
|
||||
|
@ -125,6 +135,12 @@ func goIOSBind(pkgs []*build.Package) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
err = copyFile(
|
||||
headers+"/ref.h",
|
||||
srcDir+"/ref.h")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headerFiles = append(headerFiles, title+".h")
|
||||
err = writeFile(headers+"/"+title+".h", func(w io.Writer) error {
|
||||
return iosBindHeaderTmpl.Execute(w, map[string]interface{}{
|
||||
|
@ -172,6 +188,7 @@ const iosBindInfoPlist = `<?xml version="1.0" encoding="UTF-8"?>
|
|||
`
|
||||
|
||||
var iosModuleMapTmpl = template.Must(template.New("iosmmap").Parse(`framework module "{{.Module}}" {
|
||||
header "ref.h"
|
||||
{{range .Headers}} header "{{.}}"
|
||||
{{end}}
|
||||
export *
|
||||
|
|
Loading…
Reference in New Issue