// 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.

/*
Gobind generates language bindings that make it possible to call Go code
and pass objects from Java.

Using gobind

Gobind takes a Go package and generates bindings for all of the exported
symbols. The exported symbols define the cross-language interface.

The gobind tool generates both an API stub in Java, and binding code in
Go. Start with a Go package:

	package hi

	import "fmt"

	func Hello(name string) {
		fmt.Println("Hello, %s!\n", name)
	}

Generate a Go binding package and Java stubs:

	go install golang.org/x/mobile/cmd/gobind
	gobind -lang=go github.com/crawshaw/hi > hi/go_hi/go_hi.go
	gobind -lang=java github.com/crawshaw/hi > hi/Hi.java

The generated Go package, go_hi, must be linked into your Go program:

	import _ "github.com/crawshaw/hi/go_hi"

Type restrictions

At present, only a subset of Go types are supported.

All exported symbols in the package must have types that are supported.
Supported types include:

	- Signed integer and floating point types.

	- String and boolean types.

	- Byte slice types.

	- Any function type all of whose parameters and results have
	  supported types. Functions must return either no results,
	  one result, or two results where the type of the second is
	  the built-in 'error' type.

	- Any interface type, all of whose exported methods have
	  supported function types.

	- Any struct type, all of whose exported methods have
	  supported function types and all of whose exported fields
	  have supported types.

Unexported symbols have no effect on the cross-language interface, and
as such are not restricted.

The set of supported types will eventually be expanded to cover all Go
types, but this is a work in progress.

Exceptions and panics are not yet supported. If either pass a language
boundary, the program will exit.

Passing Go objects to foreign languages

Consider a type for counting:

	package mypkg

	type Counter struct {
		Value int
	}

	func (c *Counter) Inc() { c.Value++ }

	func New() *Counter { return &Counter{ 5 } }

The generated bindings enable Java programs to create and use a Counter.

	public abstract class Mypkg {
		private Mypkg() {}
		public static final class Counter {
			public void Inc() { ... }
			public long GetValue() { ... }
			public void SetValue(long value) { ... }
		}
		public static Counter New() { ... }
	}

The package-level function New can be called like so:

	Counter c = Mypkg.New()

returns a Java Counter, which is a proxy for a Go *Counter. Calling the Inc
and Get methods will call the Go implementations of these methods.

Passing foreign language objects to Go

For a Go interface:

	package myfmt

	type Printer interface {
		Print(s string)
	}

	func PrintHello(p Printer) {
		p.Print("Hello, World!")
	}

gobind generates a Java stub that can be used to implement a Printer:

	public abstract class Myfmt {
		private Myfmt() {}
		public interface Printer {
			public void Print(String s);

			public static abstract class Stub implements Printer {
				...
			}

			...
		}

		public static void PrintHello(Printer p) { ... }
	}

You can extend Myfmt.Printer.Stub to implement the Printer interface, and
pass it to Go using the PrintHello package function:

	public class SysPrint extends Myfmt.Printer.Stub {
		public void Print(String s) {
			System.out.println(s);
		}
	}

The Java implementation can be used like so:

	Myfmt.Printer printer = new SysPrint();
	Myfmt.PrintHello(printer);

Avoid reference cycles

The language bindings maintain a reference to each object that has been
proxied. When a proxy object becomes unreachable, its finalizer reports
this fact to the object's native side, so that the reference can be
removed, potentially allowing the object to be reclaimed by its native
garbage collector.  The mechanism is symmetric.

However, it is possible to create a reference cycle between Go and
Java objects, via proxies, meaning objects cannot be collected. This
causes a memory leak.

For example, if a Go object G holds a reference to the Go proxy of a
Java object J, and J holds a reference to the Java proxy of G, then the
language bindings on each side must keep G and J live even if they are
otherwise unreachable.

We recommend that implementations of foreign interfaces do not hold
references to proxies of objects. That is: if you extend a Stub in
Java, do not store an instance of Seq.Object inside it.

Further reading

Examples can be found in http://golang.org/x/mobile/example.

Design doc: http://golang.org/s/gobind
*/
package main // import "golang.org/x/mobile/cmd/gobind"
