/unsafecgo

cgo calls via assembly trampoline

Primary LanguageGoMIT LicenseMIT

unsafecgo

MIT License GoDoc Go Report Card Releases

unsafecgo provides Cgo calls via assembly trampoline. Inspired by rustgo.

Installation

go get github.com/octu0/unsafecgo

Example

package main

/*
#include <stdio.h>
void hello() {
  fprintf(stderr, "hello world\n");
}
*/
import "C"

import (
	"fmt"
	"reflect"
	"runtime"
	"unsafe"

	"github.com/octu0/unsafecgo"
)

func cgo_helloworld() {
	fmt.Println("cgo")

	C.hello()
}

func unsafecgo_helloworld() {
	fmt.Println("unsafecgo.Call")

	p := unsafe.Pointer(reflect.ValueOf(C.hello).Pointer())
	unsafecgo.Call(p) // call C.hello()
	runtime.KeepAlive(p)
}

func main() {
	cgo_helloworld()
	unsafecgo_helloworld()
}

Benchmark

goos: darwin
goarch: amd64
pkg: github.com/octu0/unsafecgo/benchmark
cpu: Intel(R) Core(TM) i5-8210Y CPU @ 1.60GHz
BenchmarkUnsafecgo
BenchmarkUnsafecgo/cgo/malloc_free
BenchmarkUnsafecgo/cgo/malloc_free-4              971646              1236 ns/op            1024 B/op          1 allocs/op
BenchmarkUnsafecgo/unsafecgo/malloc_free
BenchmarkUnsafecgo/unsafecgo/malloc_free-4       1340142               910.4 ns/op             0 B/op          0 allocs/op
BenchmarkUnsafecgo/cgo/calc
BenchmarkUnsafecgo/cgo/calc-4                    3667410               311.5 ns/op             0 B/op          0 allocs/op
BenchmarkUnsafecgo/unsafecgo/calc
BenchmarkUnsafecgo/unsafecgo/calc-4             16357767                74.31 ns/op            0 B/op          0 allocs/op
BenchmarkUnsafecgo/cgo/nop_call
BenchmarkUnsafecgo/cgo/nop_call-4               17337052                65.60 ns/op            0 B/op          0 allocs/op
BenchmarkUnsafecgo/unsafecgo/nop_call
BenchmarkUnsafecgo/unsafecgo/nop_call-4         369709251                3.211 ns/op           0 B/op          0 allocs/op
PASS

License

MIT, see LICENSE file for details.