Sharing Golang packages to C and Go

前端之家收集整理的这篇文章主要介绍了Sharing Golang packages to C and Go前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Sharing Golang packages to C and Go

Sun,Aug 23,2015

programming languagestutorial

The latestGo 1.5version is out. As part of thenew features,Go compilercan compile packages as a shared libraries.

It accepts-buildmodeargument that determines how a package is compiled. These are the following options:

  • archive: Build the listed non-main packages into .a files. Packages named main are ignored.
  • c-archive: Build the listed main package,plus all packages it imports,into a C archive file.
  • c-shared: Build the listed main packages,plus all packages that they import,into C shared libraries.
  • shared: Combine all the listed non-main packages into a single shared library.
  • exe: Build the listed main packages and everything they import into executables. Packages not named main are ignored.

By default,listed main packages are built into executables and listed non-main packages are built into .a files.

In this article we will explore two major ways to share libraries between Go and C:

Using shared library in Go

Assume thatGOPATHcontains this structure:

.
├── calc
│ └── calc.go
└── cashier
    └── main.go

Thecalcpackage contains a set of functions that do arithmetic opertaions:

// filename: calc.go
package calc

func Sum(x,y int) int {
    return x + y
}

Before compile any shared library,the standard builtin packages should be installed as shared library. This will allow any other shared library to link with them.

$ go install -buildmode=shared -linkshared std

Then thecalcpackage can be compiled as shared library linked tostdlibraries:

$ go install -buildmode=shared -linkshared calc

Due to aissue,building and installing shared library should be from$GOPATH/src.

Lets use the shared librarycalcin thecashierapplication:

// package: cashier
// filename: main.go
package main

import "calc"
import "fmt"

func main() {
  fmt.Println("Cashier Application")
    fmt.Printf("Result: %d\n",calc.Sum(5,10))
}

The application should be compiled and linked withcalclibrary with the following command:

$ go build -linkshared -o app cashier

The output of executing the application is:

$ ./app
Cashier Application
Result: 15

Note that this feature is available onlinux/amd64platform or whengccgocompiler is used.

Using shared Go library in C

Go functions can be executed from C applications. They should be exported by using the following comment line:

//export <your_function_name>

In the code snippet below,the functionSayHelloandSayByeare exported:

// package name: nautilus
package main

import "C"
import "fmt"

//export SayHello
func SayHello(name string) {
	fmt.Printf("Nautilus says: Hello,%s!\n",name)
}

//export SayBye
func SayBye() {
	fmt.Println("Nautilus says: Bye!")
}

func main() {
	// We need the main function to make possible
	// CGO compiler to compile the package as C shared library
}

The packaged should be compiled withbuildmodeflagsc-sharedorc-archive:

// as c-shared library
$ go build -buildmode=c-shared -o nautilus.a nautilus.go
// as c-archive 
$ go build -buildmode=c-archive -o nautilus.a nautilus.go

As result theGOcompiler will produce a static/dynamicClibrarynautilus.aand header filenautilus.h. The header file contains type definitions that marshall and unmarshall data betweenGoandC:

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
typedef __complex float GoComplex64;
typedef __complex double GoComplex128;
typedef struct { char *p; GoInt n; } GoString;
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif


extern void SayHello(GoString p0);

extern void SayBye();

#ifdef __cplusplus
}
#endif

The header filenautilus.hshoulde be imported from everyCapplication that executedSayHelloandSayByefunctions.

In the example below,theSayHellofunction is called with parameter of typeGoString. It includeschar*field and its length.

// filename: _wale.c
#include "nautilus.h"
#include <stdio.h>

int main() {
  printf("This is a C Application.\n");
  GoString name = {"Jack",4};
  SayHello(name);
  SayBye();
  return 0;
}

The_wale.cfile is compiled with the following command:

$ gcc -o _wale _wale.c nautilus.a

Execution produce the following output:

$ ./wale
This is a C Application.
Nautilus says: Hello,Jack!
Nautilus says: Bye!

Conclusion

Sharing libraries betweenCandGogives opportunity to build greater and better application by using the best from both worlds. This provides to a legacy system a modern language that can improve their maintainance costs and business needs. It maximize code reusability in theGoecosystem.

原文链接:https://www.f2er.com/go/188658.html

猜你在找的Go相关文章