April 18, 2019

Gomobile - Under the hood

Photo by Nathan Van Egmond on Unsplash

To understand and fully appreciate what Gomobile does, we’ll need to go through a few concepts (features) related to Java/Objective-C and Go itself and see how Gomobile brings them together. Primarily Java and Objective-C ‘s ability to communicate with c / c ++ and go’s ability to generate c shared libraries.

C and C++ support in Java and Objective-C

Java and Objective-C applications have had the ability to interact with libraries written in c and c ++ for a while.
Java -
Communicates with C libraries using JNI framework. Many of the standard library classes depend on JNI to provide functionality to the developer and the user, e.g. file I/O and sound capabilities. Including performance- and platform-sensitive API implementations in the standard library allows all Java applications to access this functionality in a safe and platform-independent manner.
Objective-C -
Superset of c, and has access to c libraries.

Go and CGo

cgo is a library that allows Go programs to interoperate with C libraries. We are interested with a specific feature that cgo provides which allows us to compile Go files into C shared libraries. Go 1.5 introduced execution modes that permits Go methods to be exposed using a C-style api. To read more about execution modes and what their capabilites are - https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#heading=h.44n2lm20ate5

Cgo has a few requirements for a Go file to be compiled into a shared library.

  1. The package must be a main package. The compiler will build the package and all of its dependencies into a single shared object binary.

  2. The source must import the pseudo-package “C”.

  3. Use the //export comment to annotate functions you wish to make accessible to other languages.

  4. An empty main function must be declared.

If the following requirements are met then any .go file can be converted into a shared library that contains a .h and a .so file. The .h file contains the exported methods. A in depth example of creating your own .so and .h file is available here - https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf

So what does Gomobile do?

We know that -

  1. Java and Objective-C can talk to C
  2. Using cgo we can make a shared library that can be called by other c files or Java and Objective-C via (1)

gomobile bind brings together both of these concepts to generate a library that applications can use to call Go code.

Example code (Objective-C example) –

  1. If we have a file hello.go -> package hello func HelloWorld() {}

  2. When we run gomobile bind –target=ios, a Hello.framework is created that contains a hello.Objective-C.h and binary called hello. Hello.Objective-C.h is a header file.

  3. Now we know that a shared library has been generated and we know that our hello.go does not meet the requirements for a go a file to be converted by cgo. This is where Gomobile comes in, it generates a proxy go file that adheres to cgo requirements and then runs the cgo tool to create a public header and a shared library that can be then be called by Java and Objective-C. So gomobile bind creates a temporary file for hello.go and passes it to cgo to generate a .framework or .aar archives.

References -

  1. https://medium.com/learning-the-go-programming-language/calling-go-functions-from-other-languages-4c7d8bcc69bf
  2. https://docs.google.com/document/d/1nr-TQHw_er6GOQRsF6T43GGhFDelrAP0NqSS_00RgZQ/edit?pli=1#
  3. https://docs.google.com/document/d/1y9hStonl9wpj-5VM-xWrSTuEJFUAxGOXOhxvAs7GZHE/edit

Part 4 of 4 in the Gomobile series.

Series Start | Gomobile - Caveat Emptor