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.
-
The package must be a main package. The compiler will build the package and all of its dependencies into a single shared object binary.
-
The source must import the pseudo-package “C”.
-
Use the //export comment to annotate functions you wish to make accessible to other languages.
-
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 -
- Java and Objective-C can talk to C
- 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) –
-
If we have a file hello.go ->
package hello func HelloWorld() {}
-
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.
-
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.