如何获取函数的地址?

时间:2016-12-08 15:49:55

标签: pointers go cgo

是否可以在Go中获取函数引用的地址?

这样的东西
func myFunction() {
}

// ...

unsafe.Pointer(&myFunction)

就是这样就不行了。我的猜测是不可能的,但我还没有找到任何证据。

编辑:背景

我的问题的背景来自处理CGO和C函数指针。 这有效:

/*
void go_myFunction();

typedef void (*myFunction_f)();

myFunction_f pMyFunction;
*/
import "C"

//export go_myFunction
func go_myFunction() {
// ...
}

func SetupFp() {
  C.pMyFunction = (*[0]byte)(unsafe.Pointer(C.go_myFunction))
}

我也知道文档声明将指针传递给go函数不起作用。但上面的代码似乎没有那么远。我只是想知道是否可以某种方式跳过导出步骤。

3 个答案:

答案 0 :(得分:5)

Go中的

function类型无法解决且无法比较,因为:

  

函数指针表示函数的代码。函数文字创建的匿名函数的代码只在内存中存储一​​次,无论返回匿名函数值的代码运行多少次。

Original answer

如果您需要比较功能的地址,可以使用reflect.Pointer进行比较。但是这种操作无论如何都是无意义的,因为:

  

如果v的类型是Func,则返回的指针是底层代码指针,但不一定足以唯一地标识单个函数。唯一的保证是当且仅当v是nil func值时结果为零。

答案 1 :(得分:2)

您可以获得这样的Go函数的地址:

package main

import (
    "fmt"
    "reflect"
)

func HelloWorld() {
    fmt.Println("Hello, world!")
}

func main() {
    var ptr uintptr = reflect.ValueOf(HelloWorld).Pointer()
    fmt.Printf("0x%x", ptr)
}

答案 2 :(得分:0)

可以得到函数使用函数的地址GetFuncAddr

    package main

     import (
         "fmt"
         "unsafe"
         "reflect"
      )

     func HelloWorld() {
        fmt.Println("Hello, world!")
     }


     func GetFuncAddr(i interface{}) uintptr {
     type IHeader struct {
        typ  uintptr
        word uintptr
      }
    
    return (*IHeader)(unsafe.Pointer(&i)).word
    }

  func main() {
   tmp := HelloWorld
   ptr1 := *(*uintptr)(unsafe.Pointer(&tmp)) //Way 1

   ptr2 := GetFuncAddr(HelloWorld)  //Way 2
   fmt.Printf("0x%x = 0x%x", ptr1, ptr2)

   //Thits is not are functon addrress!!!
   BadPTR1 := reflect.ValueOf(HelloWorld).Pointer()
   BadPTR2 := **(**uintptr)(unsafe.Pointer(&tmp)) //dereferenced pointer
   fmt.Printf("\nBAD: 0x%x = 0x%x", BadPTR1 , BadPTR2 )
  }