我正在使用golang调用类似char* fn()
的Dll函数,该dll不是由我自己编写的,因此无法更改。这是我的代码:
package main
import (
"fmt"
"syscall"
"unsafe"
)
func main() {
dll := syscall.MustLoadDLL("my.dll")
fn := dll.MustFindProc("fn")
r, _, _ := fn.Call()
p := (*byte)(unsafe.Pointer(r))
// define a slice to fill with the p string
data := make([]byte, 0)
// loop until find '\0'
for *p != 0 {
data = append(data, *p) // append 1 byte
r += unsafe.Sizeof(byte(0)) // move r to next byte
p = (*byte)(unsafe.Pointer(r)) // get the byte value
}
name := string(data) // convert to Golang string
fmt.Println(name)
}
我有一些问题:
append()
会导致性能问题吗? unsafe.Pointer(r)
导致linter govet显示警告possible misuse of unsafe.Pointer
,但代码运行正常,如何避免出现此警告? 解决方案:这可以通过在-unsafeptr=false
命令行中添加govet
来解决,对于vim-ale,请添加let g:ale_go_govet_options = '-unsafeptr=false'
。 最佳答案
将uintptr转换为upointer是haram。
您必须阅读规则:
https://golang.org/pkg/unsafe/#Pointer
但是有一种骇人听闻的方式,不应产生警告:
//go:linkname gostringn runtime.gostringn
func gostringn(p uintptr, l int) string
//go:linkname findnull runtime.findnull
//go:nosplit
func findnull(s uintptr) int
// ....
name := gostringn(r, findnull(r))
函数使用指针,但是我们从运行时将它们链接为uintptr,因为它们具有相同的sizeof。
可能在理论上起作用。但是也皱眉。
就像JimB所说的那样,回到您的代码中,您可以一行代码完成:
name := C.GoString((*C.char)(unsafe.Pointer(r)))
关于go - golang从dll返回char *作为返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58029398/