github.com/adwpc/xmobile@v0.0.0-20231212131043-3f9720cf0e99/cmd/gobind/doc.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Gobind generates language bindings that make it possible to call Go 7 functions from Java and Objective-C. 8 9 Typically gobind is not used directly. Instead, a binding is 10 generated and automatically packaged for Android or iOS by 11 `gomobile bind`. For more details on installing and using the gomobile 12 tool, see https://github.com/adwpc/xmobile/cmd/gomobile. 13 14 # Binding Go 15 16 Gobind generates target language (Java or Objective-C) bindings for 17 each exported symbol in a Go package. The Go package you choose to 18 bind defines a cross-language interface. 19 20 Bindings require additional Go code be generated, so using gobind 21 manually requires calling it twice, first with -lang=<target>, where 22 target is either java or objc, and again with -lang=go. The generated 23 package can then be _ imported into a Go program, typically built 24 with -buildmode=c-archive for iOS or -buildmode=c-shared for Android. 25 These details are handled by the `gomobile bind` command. 26 27 # Passing Go objects to target languages 28 29 Consider a type for counting: 30 31 package mypkg 32 33 type Counter struct { 34 Value int 35 } 36 37 func (c *Counter) Inc() { c.Value++ } 38 39 func NewCounter() *Counter { return &Counter{ 5 } } 40 41 In Java, the generated bindings are, 42 43 public abstract class Mypkg { 44 public static native Counter newCounter(); 45 } 46 47 and 48 49 public final class Counter { 50 public Counter() { ... } 51 52 public final long getValue(); 53 public final void setValue(long v); 54 public void inc(); 55 56 } 57 58 The package-level function newCounter can be called like so: 59 60 Counter c = Mypkg.newCounter() 61 62 For convenience, functions on the form NewT(...) *T are converted to constructors for T: 63 64 Counter c = new Counter() 65 66 Both forms returns a Java Counter, which is a proxy for a Go *Counter. Calling the inc, getValue and 67 setValue methods will call the Go implementations of these methods. 68 69 Similarly, the same Go package will generate the Objective-C interface 70 71 @class GoMypkgCounter; 72 73 @interface GoMypkgCounter : NSObject { 74 } 75 76 @property(strong, readonly) id ref; 77 - (void)inc; 78 - (int64_t)value; 79 - (void)setValue:(int64_t)v; 80 @end 81 82 FOUNDATION_EXPORT GoMypkgCounter* GoMypkgNewCounter(void); 83 84 The equivalent of calling newCounter in Go is GoMypkgNewCounter in Objective-C. 85 The returned GoMypkgCounter* holds a reference to an underlying Go 86 *Counter. 87 88 # Passing target language objects to Go 89 90 For a Go interface: 91 92 package myfmt 93 94 type Printer interface { 95 Print(s string) 96 } 97 98 func PrintHello(p Printer) { 99 p.Print("Hello, World!") 100 } 101 102 gobind generates a Java interface that can be used to implement a Printer: 103 104 public abstract class Myfmt { 105 public static void printHello(Printer p0); 106 } 107 108 and 109 110 public interface Printer { 111 public void print(String s); 112 } 113 114 You can implement Printer, and pass it to Go using the printHello 115 package function: 116 117 public class SysPrint implements Printer { 118 public void print(String s) { 119 System.out.println(s); 120 } 121 } 122 123 The Java implementation can be used like so: 124 125 Printer printer = new SysPrint(); 126 Myfmt.printHello(printer); 127 128 For Objective-C binding, gobind generates a protocol that declares 129 methods corresponding to Go interface's methods. 130 131 @protocol GoMyfmtPrinter 132 - (void)Print:(NSString*)s; 133 @end 134 135 FOUNDATION_EXPORT void GoMyfmtPrintHello(id<GoMyfmtPrinter> p0); 136 137 Any Objective-C classes conforming to the GoMyfmtPrinter protocol can be 138 passed to Go using the GoMyfmtPrintHello function: 139 140 @interface SysPrint : NSObject<GoMyfmtPrinter> { 141 } 142 @end 143 144 @implementation SysPrint { 145 } 146 - (void)Print:(NSString*)s { 147 NSLog("%@", s); 148 } 149 @end 150 151 The Objective-C implementation can be used like so: 152 153 SysPrint* printer = [[SysPrint alloc] init]; 154 GoMyfmtPrintHello(printer); 155 156 # Type restrictions 157 158 At present, only a subset of Go types are supported. 159 160 All exported symbols in the package must have types that are supported. 161 Supported types include: 162 163 - Signed integer and floating point types. 164 165 - String and boolean types. 166 167 - Byte slice types. Note that byte slices are passed by reference, 168 and support mutation. 169 170 - Any function type all of whose parameters and results have 171 supported types. Functions must return either no results, 172 one result, or two results where the type of the second is 173 the built-in 'error' type. 174 175 - Any interface type, all of whose exported methods have 176 supported function types. 177 178 - Any struct type, all of whose exported methods have 179 supported function types and all of whose exported fields 180 have supported types. 181 182 Unexported symbols have no effect on the cross-language interface, and 183 as such are not restricted. 184 185 The set of supported types will eventually be expanded to cover more 186 Go types, but this is a work in progress. 187 188 Exceptions and panics are not yet supported. If either pass a language 189 boundary, the program will exit. 190 191 # Reverse bindings 192 193 Gobind also supports accessing API from Java or Objective C from Go. 194 Similar to how Cgo supports the magic "C" import, gobind recognizes 195 import statements that start with "Java/" or "ObjC/". For example, 196 to import java.lang.System and call the static method currentTimeMillis: 197 198 import "Java/java/lang/System" 199 200 t := System.CurrentTimeMillis() 201 202 Similarly, to import NSDate and call the static method [NSDate date]: 203 204 import "ObjC/Foundation/NSDate" 205 206 d := NSDate.Date() 207 208 Gobind also supports specifying particular classes, interfaces or 209 protocols a particular Go struct should extend or implement. For example, 210 to create an Android Activity subclass MainActivity: 211 212 import "Java/android/app/Activity" 213 214 type MainActivity struct { 215 app.Activity 216 } 217 218 Gobind also recognizes Java interfaces as well as Objective C classes and 219 protocols the same way. 220 221 For more details on binding the native API, see the design proposals, 222 https://golang.org/issues/16876 (Java) and https://golang.org/issues/17102 223 (Objective C). 224 225 # Avoid reference cycles 226 227 The language bindings maintain a reference to each object that has been 228 proxied. When a proxy object becomes unreachable, its finalizer reports 229 this fact to the object's native side, so that the reference can be 230 removed, potentially allowing the object to be reclaimed by its native 231 garbage collector. The mechanism is symmetric. 232 233 However, it is possible to create a reference cycle between Go and 234 objects in target languages, via proxies, meaning objects cannot be 235 collected. This causes a memory leak. 236 237 For example, in Java: if a Go object G holds a reference to the Go 238 proxy of a Java object J, and J holds a reference to the Java proxy 239 of G, then the language bindings on each side must keep G and J live 240 even if they are otherwise unreachable. 241 242 We recommend that implementations of foreign interfaces do not hold 243 references to proxies of objects. That is: if you implement a Go 244 interface in Java, do not store an instance of Seq.Object inside it. 245 246 # Further reading 247 248 Examples can be found in http://github.com/adwpc/xmobile/example. 249 250 Design doc: http://golang.org/s/gobind 251 */ 252 package main // import "github.com/adwpc/xmobile/cmd/gobind"