Jesse Brands
Jesse Brands

Reputation: 2887

unsafe.Pointer to []byte in Go

I'm trying to write a screenshot function for my OpenGL project in Go, I'm using the OpenGL bindings found here:

https://github.com/go-gl/glow

This is the code I use to make a screenshot, or well, it's what I'm working on:

    width, height := r.window.GetSize()
    pixels := make([]byte, 3*width*height)

    // Read the buffer into memory
    var buf unsafe.Pointer
    gl.PixelStorei(gl.UNPACK_ALIGNMENT, 1)
    gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGB, gl.UNSIGNED_BYTE, buf)
    pixels = []byte(&buf) // <-- LINE 99

This triggers the following error during compile time:

video\renderer.go:99: cannot convert &buf (type *unsafe.Pointer) to type []byte.

How do I convert unsafe.Pointer to a byte array?

Upvotes: 0

Views: 19047

Answers (2)

YenForYang
YenForYang

Reputation: 3304

How do I convert unsafe.Pointer to a byte array?

This is probably an XY problem. You don't really need to convert an unsafe.Pointer to a byte array/slice from what I can see.

The root of the issue lies at your attempt in passing buf to gl.ReadPixels. I'm not familiar with the go-gl package, but it looks like you should be using gl.Ptr(data interface{}) to pass an unsafe.Pointer to an existing buffer (which I assume is what pixels is):

    width, height := r.window.GetSize()
    pixels := make([]byte, 3*width*height)

    // ...

    buf := gl.Ptr(&pixels[0]) // unsafe.Pointer pointing to 1st element in pixels
    gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGB, gl.UNSIGNED_BYTE, buf)
    // Also could try (I believe this requires OpenGL 4.5):
    gl.ReadPixels(0, 0, int32(width), int32(height), gl.RGB, gl.UNSIGNED_BYTE, int32(len(pixels)), buf)
    // Access pixels as normal, no need for conversion.

That said, it is possible to go from an unsafe.Pointer to a byte slice/array back to a byte array/slice. To avoid redundancy, I suggest looking at this existing SO question: How to create an array or a slice from an array unsafe.Pointer in golang?.

Long story short, though, if you have access to Go 1.17 you can simply do the following to get a []byte slice.

pixels = unsafe.Slice((*byte)(buf), desiredSliceLen)

Upvotes: 0

Not_a_Golfer
Not_a_Golfer

Reputation: 49275

Since unsafe.Pointer is already a pointer, you can't use a pointer to unsafe.Pointer, but you should use it directly. A simple example:

bytes := []byte{104, 101, 108, 108, 111}

p := unsafe.Pointer(&bytes)
str := *(*string)(p) //cast it to a string pointer and assign the value of this pointer
fmt.Println(str) //prints "hello"

Upvotes: 7

Related Questions