github.com/notti/nocgo@v0.0.0-20190619201224-fc443047424c/steps/4_func/main.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"unsafe"
     7  )
     8  
     9  //go:linkname funcPC runtime.funcPC
    10  func funcPC(f interface{}) uintptr
    11  
    12  func callWrapper()
    13  
    14  type funcStorage struct {
    15  	code    uintptr
    16  	argsize uintptr
    17  	retsize uintptr
    18  	value   int
    19  }
    20  
    21  func fake(s *funcStorage, i *[2]int) int64 {
    22  	fmt.Println("in fake: ", s.value, i[0], i[1])
    23  	return int64(i[0] + 100 + s.value)
    24  }
    25  
    26  var alignSize = unsafe.Sizeof(uintptr(0))
    27  
    28  func emulate(x reflect.Value) {
    29  	ftype := x.Elem().Type()
    30  	fptr := x.Pointer()
    31  	fmt.Println(fptr, ftype)
    32  	toassign := new(funcStorage)
    33  	toassign.code = funcPC(callWrapper)
    34  	for i := 0; i < ftype.NumIn(); i++ {
    35  		size := ftype.In(i).Size()
    36  		size = (size + alignSize - 1) &^ (alignSize - 1)
    37  		toassign.argsize += size
    38  	}
    39  	for i := 0; i < ftype.NumOut(); i++ {
    40  		size := ftype.Out(i).Size()
    41  		size = (size + alignSize - 1) &^ (alignSize - 1)
    42  		toassign.retsize += size
    43  	}
    44  	toassign.value = -5
    45  	*(*unsafe.Pointer)(unsafe.Pointer(fptr)) = unsafe.Pointer(toassign)
    46  	fmt.Println(toassign)
    47  }
    48  
    49  func main() {
    50  	var test func(int, byte, int) int64
    51  	var test1 func(int, int) int64
    52  	var test2 func(int, string) int64
    53  
    54  	emulate(reflect.ValueOf(&test))
    55  	emulate(reflect.ValueOf(&test1))
    56  	emulate(reflect.ValueOf(&test2))
    57  
    58  	fmt.Println("test 1: ", test(10, 1, 2))
    59  	fmt.Println("test 2: ", test(11, 2, 3))
    60  	fmt.Println("test 3: ", test(12, 3, 4))
    61  
    62  	fmt.Println("test 1: ", test1(10, 1))
    63  	fmt.Println("test 2: ", test1(11, 2))
    64  	fmt.Println("test 3: ", test1(12, 3))
    65  
    66  	fmt.Println("test2 1: ", test2(10, "1, 2"))
    67  	fmt.Println("test2 2: ", test2(11, "2, 3"))
    68  	fmt.Println("test2 3: ", test2(12, "3, 4"))
    69  }