go - golang从dll返回char *作为返回值

标签 go unsafe-pointers

我正在使用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)
}

我有一些问题:
  • 有更好的方法吗?有成百上千个这样的dll函数,我必须为所有函数编写循环。
  • 对于非常长的字符串(如100k +字节),append()会导致性能问题吗?
  • 解决了unsafe.Pointer(r)导致linter govet显示警告possible misuse of unsafe.Pointer,但代码运行正常,如何避免出现此警告? 解决方案:这可以通过在-unsafeptr=false命令行中添加govet来解决,对于vim-ale,请添加let g:ale_go_govet_options = '-unsafeptr=false'

  • enter image description here

    最佳答案

    将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/

    相关文章:

    go - 精度乘以 big.Float 的奇怪损失

    c - 如何从 UnsafeMutableRawPointer 获取页对齐地址?

    go - 查找触发 Cloud Function 的 Pub/Sub 消息的 messageID

    swift - 指向 Swift 中最后一个数组元素的不安全指针

    swift - 如何在 Swift 中处理 CFSocketCallBackType.dataCallback?

    null - Swift:gettimeofday 和不安全指针

    swift - CGPathAddArc 在创建路径时遇到一些问题

    c - 您如何构建Pion mediadevices webrtc示例?

    go - golang的模板中如何多次使用parse

    go - 为什么 atomic.StoreUint32 优于 sync.Once 中的正常分配?