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