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