// 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
functions from Java and Objective-C.

Typically gobind is not used directly. Instead, a binding is
generated and automatically packaged for Android or iOS by
`gomobile bind`. For more details on installing and using the gomobile
tool, see https://golang.org/x/mobile/cmd/gomobile.

Binding Go

Gobind generates target language (Java or Objective-C) bindings for
each exported symbol in a Go package. The Go package you choose to
bind defines a cross-language interface.

Bindings require additional Go code be generated, so using gobind
manually requires calling it twice, first with -lang=<target>, where
target is either java or objc, and again with -lang=go. The generated
package can then be _ imported into a Go program, typically built
with -buildmode=c-archive for iOS or -buildmode=c-shared for Android.
These details are handled by the `gomobile bind` command.

Passing Go objects to target languages

Consider a type for counting:

	package mypkg

	type Counter struct {
		Value int
	}

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

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

In Java, the generated bindings are,

	public abstract class Mypkg {
		public static native Counter newCounter();
	}

and

	public final class Counter {
		public Counter() { ... }

		public final long getValue();
		public final void setValue(long v);
		public void inc();

	}

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

	Counter c = Mypkg.newCounter()

For convenience, functions on the form NewT(...) *T are converted to constructors for T:

	Counter c = new Counter()

Both forms returns a Java Counter, which is a proxy for a Go *Counter. Calling the inc, getValue and
setValue methods will call the Go implementations of these methods.

Similarly, the same Go package will generate the Objective-C interface

	@class GoMypkgCounter;

	@interface GoMypkgCounter : NSObject {
	}

	@property(strong, readonly) id ref;
	- (void)inc;
	- (int64_t)value;
	- (void)setValue:(int64_t)v;
	@end

	FOUNDATION_EXPORT GoMypkgCounter* GoMypkgNewCounter(void);

The equivalent of calling newCounter in Go is GoMypkgNewCounter in Objective-C.
The returned GoMypkgCounter* holds a reference to an underlying Go
*Counter.

Passing target 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 interface that can be used to implement a Printer:

	public abstract class Myfmt {
		public static void printHello(Printer p0);
	}

and

	public interface Printer {
		public void print(String s);
	}

You can implement Printer, and pass it to Go using the printHello
package function:

	public class SysPrint implements Printer {
		public void print(String s) {
			System.out.println(s);
		}
	}

The Java implementation can be used like so:

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


For Objective-C binding, gobind generates a protocol that declares
methods corresponding to Go interface's methods.

	@protocol GoMyfmtPrinter
	- (void)Print:(NSString*)s;
	@end

	FOUNDATION_EXPORT void GoMyfmtPrintHello(id<GoMyfmtPrinter> p0);

Any Objective-C classes conforming to the GoMyfmtPrinter protocol can be
passed to Go using the GoMyfmtPrintHello function:

	@interface SysPrint : NSObject<GoMyfmtPrinter> {
	}
	@end

	@implementation SysPrint {
	}
	- (void)Print:(NSString*)s {
		NSLog("%@", s);
	}
	@end

The Objective-C implementation can be used like so:

	SysPrint* printer = [[SysPrint alloc] init];
	GoMyfmtPrintHello(printer);


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. Note that byte slices are passed by reference,
	  and support mutation.

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


Reverse bindings

Gobind also supports accessing API from Java or Objective C from Go.
Similar to how Cgo supports the magic "C" import, gobind recognizes
import statements that start with "Java/" or "ObjC/". For example,
to import java.lang.System and call the static method currentTimeMillis:

	import "Java/java/lang/System"

	t := System.CurrentTimeMillis()

Similarly, to import NSDate and call the static method [NSDate date]:

	import "ObjC/Foundation/NSDate

	d := NSDate.Date()

Gobind also supports specifying particular classes, interfaces or
protocols a particular Go struct should extend or implement. For example,
to create an Android Activity subclass MainActivity:

	import "Java/android/app/Activity"

	type MainActivity struct {
		app.Activity
	}

Gobind also recognizes Java interfaces as well as Objective C classes and
protocols the same way.

For more details on binding the the native API, see the design proposals,
https://golang.org/issues/16876 (Java) and https://golang.org/issues/17102
(Objective C).

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
objects in target languages, via proxies, meaning objects cannot be
collected. This causes a memory leak.

For example, in Java: 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 implement a Go
interface 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"
