github.com/inaneverb/ekacore/ekaunsafe/v4@v4.0.0/pointer.go (about) 1 // Copyright © 2020. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 package ekaunsafe 7 8 import ( 9 "unsafe" 10 ) 11 12 // TakeRealAddr takes and returns a real address of the variable you passed. 13 // It returns nil if nil is passed. 14 // 15 // var i int 16 // _ = &i == TakeRealAddr(i) // true 17 // 18 // This function exist to extend standard Golang & operator. 19 // Using this function you can take an address of some things, 20 // that "cannot be addressed" in Golang policy. Like functions, for example. 21 // 22 // What you CAN do with functions and their addresses: 23 // 24 // f := func(){} 25 // _ = &f // 0x... 26 // 27 // What you CANNOT do with functions and their addresses: 28 // 29 // func foo() {} 30 // func bar() { _ = &foo } // compilation err 31 // 32 // What you CAN do with functions and their addresses using TakeRealAddr(): 33 // 34 // func foo() {} 35 // type T struct{} 36 // func (_ T) bar() {} 37 // 38 // func main() { 39 // var t T 40 // ptr1 := TakeRealAddr(foo) // 0x... 41 // ptr2 := TakeRealAddr((*T).bar) // 0x... 42 // ptr3 := TakeRealAddr(t.bar) // 0x... 43 // } 44 // 45 // Speaking about functions, if you want to convert it back, 46 // and be able to call a function address of which you've got by TakeRealAddr(), 47 // you need to pass it to Addr2Callable() or just use TakeCallableAddr(). 48 func TakeRealAddr(i any) unsafe.Pointer { 49 return UnpackInterface(i).Word 50 } 51 52 // TakeCallableAddr extends TakeRealAddr functionality, 53 // providing you a mechanism to get a real address of any function, 54 // using which you may: 55 // 56 // - Compare with another, obtained the same way, address; 57 // - Doing other unsafe but interest stuff with function address in C-style; 58 // - Convert that address back and call the function. 59 // 60 // It returns nil if nil is passed. 61 // 62 // Tip: 63 // Using this function you may not only compare addresses of function, 64 // convert addresses to functions, vice-versa and call them, 65 // but you can also avoid type checks while any conversion. 66 // Yes, C-style, just as we like. 67 // 68 // Usage: 69 // 70 // type F = func(f float64) (int32, int32) 71 // func foo(x1, x2 int32) (int32, int32) { return x1, x2 } 72 // untypedPtr := TakeCallableAddr(foo) 73 // x1, x2 := (*(*F)(untypedPtr))(math.PI) 74 // 75 // Now, x1 and x2 contains first and last 32 bytes of math.PI constant 76 // as Golang int32. 77 // It's a synthetic example. Real world examples will be presented later. 78 // 79 // ----- 80 // 81 // WARNING! 82 // DO NOT PASS SOMETHING BUT EITHER FUNCTIONS, FUNCTORS, CLOSURES, LAMBDAS, ETC. 83 // YOU MUST PASS ONLY THAT THING THAT MAY BE CALLED. 84 // UNDEFINED BEHAVIOUR OTHERWISE! 85 // 86 // WARNING! 87 // DESPITE, IT IS POSSIBLE TO CONVERT ADDRESS BACK AND CALL THE FUNCTION, 88 // THERE MIGHT BE SOME PROBLEMS WHEN YOU'RE TRYING TO WORK AROUND METHODS, 89 // NOT JUST FUNCTIONS. DO IT ON YOUR OWN RISK. 90 // 91 // WARNING! 92 // USING THIS FUNCTION (AND MECHANISM) IS VERY, VERY DANGEROUS. 93 // YOU MAY GET UNDEFINED BEHAVIOUR, PANIC, UNIVERSE COLLAPSE, ETC. 94 // AND IT DEPENDS ON THE GOLANG INTERNAL IMPLEMENTATIONS. 95 // 96 // THIS FUNCTION NEVER USED IN OTHER PARTS OF THAT LIBRARY. 97 // THIS FUNCTION NEVER USED IN OTHER PARTS OF THAT LIBRARY. 98 // THIS FUNCTION NEVER USED IN OTHER PARTS OF THAT LIBRARY. 99 // THIS FUNCTION NEVER USED IN OTHER PARTS OF THAT LIBRARY. 100 // 101 // BE CAREFULLY! 102 func TakeCallableAddr(fn any) unsafe.Pointer { 103 104 // There is no need nil checks, 105 // because TakeRealAddr and AddrConvert2Callable already has it 106 return Addr2Callable(TakeRealAddr(fn)) 107 } 108 109 // Addr2Callable transforms an address of some function to that kind of address, 110 // you can cast to the typed pointer of some function, dereference it and call. 111 // 112 // See TakeRealAddr(), TakeCallableAddr() for more info. 113 func Addr2Callable(realPtr unsafe.Pointer) (callablePtr unsafe.Pointer) { 114 115 type FuncPointer struct { 116 ptr unsafe.Pointer 117 } 118 119 if realPtr == nil { 120 return nil 121 } 122 123 var o = new(FuncPointer) 124 o.ptr = realPtr 125 126 return unsafe.Pointer(&o.ptr) 127 } 128 129 // Addr2Real transforms a callable address of some function, 130 // obtained by TakeCallableAddr() to a simple, real, 131 // non-callable address of that function. 132 func Addr2Real(callablePtr unsafe.Pointer) (realPtr unsafe.Pointer) { 133 134 if callablePtr == nil { 135 return nil 136 } 137 138 return *(*unsafe.Pointer)(callablePtr) 139 }