英文:
Go: convert unsafe.Pointer to function pointer and vice versa
问题
在C语言中,你可以将函数指针放入一个void指针数组中,并将它们转换回任何类型的函数指针:
extern int (*fn1)(void);
extern void (*fn2)(int);
void foo(void)
{
void *array[2];
int i;
/* 将函数指针隐式转换为void指针 */
array[0] = fn1;
array[1] = fn2;
for (i = 0; i < 2; i++)
{
int (*fp)(int, int, int);
/* 将void指针隐式转换为函数指针 */
fp = array[i];
/* 使用不同签名调用函数 */
fp(1, 2, 3);
}
}
我需要在Go语言中使用unsafe.Pointer
来实现相同的功能。问题如下:
- Go语言的函数指针能否转换为
unsafe.Pointer
? unsafe.Pointer
能否转换回与原始函数指针类型不同(或相同)的Go函数指针?
(问题不是为什么或是否需要这样做;在给定的情况下,以错误的参数调用函数并误解返回值是可以接受的,因为调用方和被调用方能够处理这种情况。)
英文:
In C you can put function pointers into an array of void pointers and convert them back to function pointers of any type:
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);
}
}
I need to do the same in Go, using unsafe.Pointers. The questions are:
- Can a Go function pointer be converted to an unsafe.Pointer?
- Can an unsafe.Pointer be converted to a Go function pointer of a different (or the same) type as the original function pointer?
(The question is not why or whether I need to do that; in the given situation it is okay to call a function with the wrong set of parameters and to misinterpret the return value because the caller and the callees are able to deal with that.)
答案1
得分: 3
如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]) // 注意,不是int
fmt.Println((*f3)(1))
}
英文:
As LinearZoetrope's answer shows, you can do this. Beware that you can do bad things:
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))
}
答案2
得分: 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
当然,你可能非常清楚尝试这样做可能会带来的潜在问题。
英文:
It appears to work:
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)
}
Will print
> 4607182418800017408
>
> 4607182418800017408
Of course, you're probably well aware of the potential problems with trying this.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论