zoukankan      html  css  js  c++  java
  • go share library

    http://blog.ralch.com/tutorial/golang-sharing-libraries/

     


    Sharing Golang packages to C and Go

    The latest Go 1.5 version is out. As part of the new features, Go compiler can compile packages as a shared libraries.

    It accepts -buildmode argument 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 that GOPATH contains this structure:

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

    The calc package 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 the calc package can be compiled as shared library linked to std libraries:

    $ go install -buildmode=shared -linkshared calc
    

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

    Lets use the shared library calc in the cashier application:

    // package: cashier
    // filename: main.go
    package main
    
    import "calc"
    import "fmt"
    
    func main() {
      fmt.Println("Cashier Application")
        fmt.Printf("Result: %d
    ", calc.Sum(5, 10))
    }
    

    The application should be compiled and linked with calc library 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 on linux/amd64 platform or when gccgo compiler 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 function SayHello and SayBye are exported:

    // package name: nautilus
    package main
    
    import "C"
    import "fmt"
    
    //export SayHello
    func SayHello(name string) {
    	fmt.Printf("Nautilus says: Hello, %s!
    ", 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 with buildmode flags c-shared or c-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 the GO compiler will produce a static/dynamic C library nautilus.a and header file nautilus.h. The header file contains type definitions that marshall and unmarshall data between Go and C:

    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 file nautilus.h shoulde be imported from every C application that executed SayHello and SayBye functions.

    In the example below, the SayHello function is called with parameter of type GoString. It includes char* field and its length.

    // filename: _wale.c
    #include "nautilus.h"
    #include <stdio.h>
    
    int main() {
      printf("This is a C Application.
    ");
      GoString name = {"Jack", 4};
      SayHello(name);
      SayBye();
      return 0;
    }
    

    The _wale.c file 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 between C and Go gives 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 the Go ecosystem.

  • 相关阅读:
    Java打jar包详解
    用户体验评价
    本周总结(13)
    本周总结(12)
    第一阶段意见评论
    本周总结(11)
    冲刺计划第十天
    冲刺计划第九天
    冲刺计划第八天
    冲刺计划第七天
  • 原文地址:https://www.cnblogs.com/jvava/p/5109584.html
Copyright © 2011-2022 走看看