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 }