【问题标题】:Go: convert unsafe.Pointer to function pointer and vice versaGo:将 unsafe.Pointer 转换为函数指针,反之亦然
【发布时间】:2014-05-20 22:06:10
【问题描述】:

在 C 中,您可以将函数指针放入 void 指针数组中,然后将它们转换回任何类型的函数指针:

extern int (*fn1)(void);
extern void (*fn2)(int);
void foo(void)
{
        void *array[2];
        int i;

        /* implicit cast from function pointer to void pointer */
        array[0] = fn1;
        array[1] = fn2;
        for (i = 0; i < 2; i++)
        {
                int (*fp)(int, int, int);

                /* implicit cast from void pointer to function pointer */
                fp = array[i];
                /* call function with a different signature */
                fp(1, 2, 3);
        }
}

我需要在 Go 中做同样的事情,使用 unsafe.Pointers。问题是:

  • 可以将 Go 函数指针转换为 unsafe.Pointer 吗?
  • 能否将 unsafe.Pointer 转换为与原始函数指针不同(或相同)类型的 Go 函数指针?

(问题是不是为什么或是否需要这样做;在给定的情况下,可以使用错误的参数集调用函数并误解返回值,因为调用者并且被调用者能够处理它。)

【问题讨论】:

  • 我回答:是的,它有效,但我不得不承认我非常好奇你为什么需要这样做。
  • 因为我正在 gccgo 中的 gofrontend 上工作,并且需要以树表示形式生成人工代码,以从完全相同的地址调用多个函数。我并不是真的在编写 Go 代码,但如果我能坚持使用已经在前端的用于解析 Go 源代码的类,那就少了很多工作。
  • 你不能在 C 中这样做。这是未定义的行为,一个好的编译器应该警告你。由于一系列非常好的原因,函数指针与数据指针不兼容。

标签: go function-pointers unsafe-pointers


【解决方案1】:

正如 LinearZoetrope 的回答所示,您可以这样做。小心你会做坏事:

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    f1 := func(s string) {}
    f2 := func(i int) int { return i + 1 }
    pointers := []unsafe.Pointer{
        unsafe.Pointer(&f1),
        unsafe.Pointer(&f2),
    }
    f3 := (*func(int) bool)(pointers[1]) // note, not int
    fmt.Println((*f3)(1))
}

playground

【讨论】:

  • 等等...你可以在操场上使用 unsafe 吗?那是新的(-ish)吗?
  • 不确定它有多新,但由于 NaCl 沙箱,您也可以打开网络套接字和文件:blog.golang.org/playground
  • --> 移至单独回复
  • 啊,我明白了;我试图直接获取函数的地址,但是您需要将指针存储在变量中并在其上使用 & 。谢谢。
【解决方案2】:

它似乎有效:

package main

import (
    "fmt"
    "unsafe"

    "math"
)

func main() {
    fn := print
    faked := *(*func(float64))(unsafe.Pointer(&fn))
    faked(1.0)

    // For comparison
    num := math.Float64bits(1.0)
    print(num)
}

func print(a uint64) {
    fmt.Println(a)
}

将打印

4607182418800017408

4607182418800017408

当然,您可能很清楚尝试这样做的潜在问题。

【讨论】:

  • > 当然,您可能很清楚尝试这样做的潜在问题。 -- 是的。
猜你喜欢
  • 1970-01-01
  • 2016-03-21
  • 2011-05-16
  • 1970-01-01
  • 2021-11-23
  • 2010-12-03
  • 2011-10-08
  • 2013-03-15
  • 2019-09-19
相关资源
最近更新 更多