Multi-platform library Golang

Since few people write C language Advent Calendar 2016, I thought I would write it, remembering when I was touching C language.

from here

Last year I struggled with multi-platform support,

For those of you who want to stop redeveloping multi-platform libraries, why not link jre's library ... (quivering) http://qiita.com/nothingcosmos/items/935cd0b9d62ef01ddddc

I was muttering, but in a familiar place I noticed that there is a convenient multi-platform library. Yes, everyone loves Golang.

C-shared to make Golang assets into a shared library

c-shared is a mode to build Golang as a shared library for C language. Wouldn't it be great to have Golang assets available from C?

Regarding c-shared, I referred to this article. If you want to try it, Linux or Mac environment is recommended.

http://qiita.com/yanolab/items/1e0dd7fd27f19f697285

There are many tacit understandings around cgo in Golang, Contrary to that tacit understanding, you are often smoky with incomprehensible error messages. is.

As explained in the link above, the following four points are important. * Excerpt

--Packages can only be generated in main. --The main function is not executed but must be declared. --Comment the function you want to export, "// Add export funcname." (Same as cgo) --init is executed when the library is loaded

main.go



package main

import (
  "C"
  "fmt"
  "io/ioutil"
  "net/http"
  )

//export request
func request(url string) ([]byte, error) {
  resp, err := http.Get(url)
  //error Crush, no, no
  if (err != nil) {
    return nil, err
  }
  defer resp.Body.Close()
  return ioutil.ReadAll(resp.Body)
}

func init() {
  fmt.Println("Loaded!!")
}

func main() {
}

build method (try with Linux (x64))

example



$ time go build -buildmode=c-shared -o libgo.so main.go
real  0m6.494s
user  0m9.264s
sys 0m1.432s

-rw-rw-r--1 elise elise 1393 December 4 00:47 libgo.h
-rw-rw-r--1 elise elise 6406448 December 4 00:47 libgo.so

It takes a lot of time, as expected it is a net library, size 6MB

Let's check the generated function. See libgo.h

libgo.h



/* Return type for request */
struct request_return {
  GoSlice r0;
  GoInterface r1;
};

extern struct request_return request(GoString p0);

typedef struct { const char *p; GoInt n; } GoString;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;
typedef GoInt64 GoInt;

//exportでコメントしたGoの関数がexportされています。 Also, the cgo boiler plate generated by Go is very interesting, Especially when returning the struct, but omitted here. Golang error is a problem with interface {}. What should I do if I have to write a helper to convert this to an error code?

Try calling the Go library from C

If you make the go source and the C source live together, When building with golang, it seems that even the C source code is misunderstood as the target of cgo and goes to read. I wrote the C source code in separate directories.

C/main.c


#include "libgo.h"
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) {
  GoString arg = {argv[1], strlen(argv[1])};
  struct request_return ret = request(arg);
  printf("%lld,%s\n", ret.r0.len, (char*)ret.r0.data);
  return 0;
}

Build and execution example


$ ls
C  libgo.h  libgo.so  main.go
$ cd C
$ clang main.c -lgo -L.. -I..
$ export LD_LIBRARY_PATH=..
$ export GODEBUG=cgocheck=0 #Good boys shouldn't imitate
$ a.out http://example.com

GODEBUG = cgocheck = 0 skips the Go pointer protection check. The above code points to the memory allocated by Go as it is with a pointer, so It can become an invalid pointer if it is GC'd.

Execution result


Loaded!!
1270,<!doctype html>
<html>
<head>
    <title>Example Domain</title>
    ...

Summary

As I wrote so far, buildmode = c-shared does not work on Windows, It seems that it only supports c-archive mode, so Another idea is needed. .. http://mattn.kaoriya.net/software/lang/go/20160405114638.htm

Recommended Posts

Multi-platform library Golang
golang profiling