2013-11-01 12 views
5

Sto cercando di interfacciarmi con una DLL di Windows utilizzando Go. La funzione dll che voglio usare accetta un puntatore a un array di byte. Quindi ho bisogno di dargli quella matrice di byte.Golang: array di byte dinamico non sicuro

Sto utilizzando la libreria syscall per chiamare la DLL, come dimostrato here. I miei requisiti di base sono:

  • mi viene data la dimensione richiesta per l'array di byte
  • creo l'array di byte
  • devo ottenere un puntatore alla matrice di byte
  • ho poi passare il puntatore la dll di Windows

Non riesco a capire come creare un array di byte in go e ottenere un puntatore. Questa è ovviamente un'operazione non sicura e la libreria unsafe dovrebbe aiutarmi, ma in primo luogo devo essere in grado di creare un array di byte di lunghezza dinamica. Creare una sezione con "make" non mi aiuta, a meno che non riesca a ottenere un puntatore sull'array di supporto della slice.

Qualcun altro ha riscontrato questo o ha qualche idea?

risposta

3

Bene, ho trovato una soluzione lorda. Apparentemente il structure of a slice contiene un puntatore all'array di byte di supporto, la lunghezza dell'array di backing byte e quindi la capacità dell'array di byte di supporto.

Mi interessa solo un puntatore all'array di byte, quindi ho solo bisogno del primo membro dei dati interni della sezione.

Go unsafe.Pointer non esegue il cast di una sezione su un puntatore non sicuro, ma esegue il cast di un puntatore su una sezione come puntatore non sicuro. Dato che posso lanciare un puntatore non sicuro su qualsiasi vecchio tipo di puntatore che desidero, posso lanciarlo su un puntatore a puntatore, che recupera il primo membro dei dati interni della sezione.

Ecco un esempio funzionante. Volevo un uintptr ma si poteva trasmettere a qualsiasi tipo di puntatore.

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))) 
} 

Se si voleva un *int, invece, si potrebbe fare mPtr := *(**int)(unsafe.Pointer(&m))

Questo funziona fino a quando una fetta mantiene questa struttura dati interna. Sono decisamente aperto a una soluzione più robusta che non dipenda dalla struttura degli interni di Go.

+2

Puntatore al primo elemento della matrice di supporto m: = fanno ([] int, 10) fetta è & m [0]. – alex

+0

Il mio male. Avevo provato quello che pensavo fosse & m [0] prima, e stavo ottenendo un puntatore a una copia di ciò che era in m [0]. Ovviamente ho fatto qualcosa di sbagliato, perché provandolo ora, funziona bene. – chowey