From ab610edb1652ee5e07392798a4b1f824aeb1d526 Mon Sep 17 00:00:00 2001 From: "rick.chan" Date: Wed, 6 Jan 2021 11:37:52 +0800 Subject: [PATCH] Build and Use Go Packages as C Libraries Signed-off-by: rick.chan --- ...uild_and_Use_Go_Packages_as_C_Libraries.md | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Software/Development/Language/Go/Basic/Build_and_Use_Go_Packages_as_C_Libraries.md diff --git a/Software/Development/Language/Go/Basic/Build_and_Use_Go_Packages_as_C_Libraries.md b/Software/Development/Language/Go/Basic/Build_and_Use_Go_Packages_as_C_Libraries.md new file mode 100644 index 0000000..a2ba9ea --- /dev/null +++ b/Software/Development/Language/Go/Basic/Build_and_Use_Go_Packages_as_C_Libraries.md @@ -0,0 +1,82 @@ +# Build and Use Go Packages as C Libraries + +CGO is an official builtin feature of Go, it enables the creation of Go packages that reference to C libraries. But it isn’t just that, it is achievable in the opposite direction, too. It enables creation of C libraries from Go packages so that C code can reference to Go, which is mind-blowing. + +## 1.How to + +### 1.1.Build Go package as C shared library (or shared object) + +Every Go **main** package can be built as a C shared library. + +```bash +go build -go build -buildmode c-shared -o .so +``` + +Executing above command builds target Go **main** package and all of its dependencies as a single C shared library, which can be distributed, installed and linked to every C application and applications in other programming languages that can reference C shared libraries (C++, Python, Javascript, etc). + +Note: Output C shared libraries should be named in standard form **lib\*.so**. + +### 1.2.Generate C header and export Go functions as C functions + +Building a Go **main** package as C shared library doesn’t automatically neither generate C header nor expose any Go function as C symbol. Developers have to explicitly indicate which Go functions to be exposed. + +To export a Go function as a C symbol: + +* Add comment **//export FuncName** on top of the Go function. +* The Go code file containing the function has to **import "C"**. +* The function must belong to **main** package. +* The function signature must not include neither Go struct nor* Go interface nor Go array nor variadic argument. + +```go +package main + +import "C" + +import ( + "math/rand" + "time" +) + +//export cgoCurrentMillis +func cgoCurrentMillis() C.long { + return C.long(time.Now().Unix()) +} + +//export cgoSeed +func cgoSeed(m C.long) { + rand.Seed(int64(m)) +} + +//export cgoRandom +func cgoRandom(m C.int) C.int { + return C.int(rand.Intn(int(m))) +} +``` + +Building above Go **main** package generates a C header file **\**.h along with a C shared object **\**.so. + +```cpp +// Other stuff. + +extern long int cgoCurrentMillis(); +extern void cgoSeed(long int p0); +extern int cgoRandom(int p0); +``` + +**cgoCurrentMilli**, **cgoSeed** and **cgoRandom** are exposed as C symbols in **\**.so, too. + +Now, every C application can include the generated C header, link to the output C shared library and use exposed C symbols. + +```cpp +#include +#include + +int main() { + cgoSeed(cgoCurrentMilli()); + + printf("Hello World from C!\n"); + printf("cgoRandom() -> %d\n", cgoRandom(256)); + + return 0; +} +```