Reputation: 2887
I'm trying to write a screenshot function for my OpenGL project in Go, I'm using the OpenGL bindings found here:
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
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
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