5

我正在尝试使用 Go 与 Windows dll 交互。我想使用的 dll 函数接受一个指向字节数组的指针。因此我需要给它那个字节数组。

我正在使用syscall库来调用 dll,如此处所示。我的基本要求是:

  • 我得到了字节数组所需的大小
  • 我创建字节数组
  • 我必须得到一个指向字节数组的指针
  • 然后我将指针传递给 Windows dll

我不知道如何在 go 中创建一个字节数组,并获得一个指向它的指针。这显然是一个不安全的操作,unsafe库可能会有所帮助,但我首先需要创建一个动态长度的字节数组。用“make”创建一个切片对我没有帮助,除非我可以得到一个指向切片支持数组的指针。

有没有其他人遇到过这个或有任何想法?

4

2 回答 2

3

好吧,我找到了一个总的解决方案。显然,切片的结构包含指向后备字节数组的指针、后备字节数组的长度以及后备字节数组的容量。

我只对指向字节数组的指针感兴趣,所以我只需要切片内部数据的第一个成员。

Gounsafe.Pointer不会将切片转换为不安全指针,但会将指向切片的指针转换为不安全指针。因为我可以将一个不安全的指针转换为我想要的任何旧类型的指针,所以我可以将它转换为一个指向指针的指针,它恢复切片内部数据的第一个成员。

这是一个工作示例。我想要一个uintptr,但你可以将它转换为任何指针类型。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    // Arbitrary size
    n := 4

    // Create a slice of the correct size
    m := make([]int, n)

    // Use convoluted indirection to cast the first few bytes of the slice
    // to an unsafe uintptr
    mPtr := *(*uintptr)(unsafe.Pointer(&m))

    // Check it worked
    m[0] = 987
    // (we have to recast the uintptr to a *int to examine it)
    fmt.Println(m[0], *(*int)(unsafe.Pointer(mPtr)))
}

如果你想要一个*int,你可以做mPtr := *(**int)(unsafe.Pointer(&m))

只要一个切片维护这个内部数据结构,它就可以工作。我绝对愿意接受一个不依赖于 Go 内部结构的更强大的解决方案。

于 2013-11-01T05:43:40.473 回答
3

我认为 syscall.ComputerName 实现https://golang.org/src/syscall/syscall_windows.go#395将是一个很好的例子。它使用 uint16s,而不是字节,但除此之外......

在你的情况下,它会是ptr := &myslice[0].

亚历克斯

于 2013-11-01T05:44:37.383 回答