Golang:不安全的动态字节数组

时间:2013-11-01 04:53:01

标签: arrays pointers dll go

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

我正在使用syscall图书馆来调用dll,正如所示here。我的基本要求是:

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

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

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

2 个答案:

答案 0 :(得分:3)

我找到了一个重要的解决方案。显然structure of a slice包含指向后备字节数组的指针,后备字节数组的长度,以及后备字节数组的容量。

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

Go unsafe.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的内部结构。

答案 1 :(得分:3)

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

在您的情况下,它将是ptr := &myslice[0]

亚历