// 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 code.google.com/p/go.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. - 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://code.google.com/p/go.mobile/example. Design doc: http://golang.org/s/gobind */ package main