假设我有一个带签名的 C 函数
// myclib.h
void modify(double* ptr, int N);
这会改变参数指针 ptr
指向的内存。
以下代码对于 Go 的垃圾收集器来说是否安全?是否需要 runtimer.Pinner
?
package main
// #cgo CFLAGS: -g -Wall
// #include "myclib.h"
import "C"
import (
"fmt"
"runtime"
)
func modifyWrapper(v []float64) {
ptr := (*C.double)(&v[0])
N := (C.int)(len(v))
pinner := runtime.Pinner{}
pinner.Pin(ptr)
C.modify(ptr, N)
pinner.Unpin()
}
func main() {
v := []float64{9.0, 2.0, 1.0, 4.0, 5.0}
modifyWrapper(v)
}
正确答案
<小时/>
package main
/*
#cgo CFLAGS: -g -Wall
#include <stdio.h>
void modify(double* ptr, int N) {
if (!ptr || N <= 0) {
return;
}
printf("modify: %g %dn", *ptr, N);
*ptr = 42;
printf("modify: %g %dn", *ptr, N);
}
*/
import "C"
import (
"fmt"
"unsafe"
)
func modify(v []float64) {
ptr := (*C.double)(unsafe.SliceData(v))
N := (C.int)(len(v))
C.modify(ptr, N)
}
func main() {
v := []float64{9.0, 2.0, 1.0, 4.0, 5.0}
fmt.Println(v)
modify(v)
fmt.Println(v)
}
<小时/>
[9 2 1 4 5]
modify: 9 5
modify: 42 5
[42 2 1 4 5]