all: reduce reflect usages

This commit is contained in:
Hajime Hoshi 2022-11-09 12:51:02 +09:00
parent f4b12462e6
commit 915fff96f8
4 changed files with 31 additions and 44 deletions

View File

@ -17,7 +17,6 @@ package directx
import ( import (
"fmt" "fmt"
"math" "math"
"reflect"
"runtime" "runtime"
"syscall" "syscall"
"unsafe" "unsafe"
@ -2294,11 +2293,9 @@ func (i *_ID3DBlob) Release() uint32 {
} }
func (i *_ID3DBlob) String() string { func (i *_ID3DBlob) String() string {
var str string bs := make([]byte, int(i.GetBufferSize()))
h := (*reflect.StringHeader)(unsafe.Pointer(&str)) copy(bs, unsafe.Slice((*byte)(unsafe.Pointer(i.GetBufferPointer())), i.GetBufferSize()))
h.Data = i.GetBufferPointer() return string(bs)
h.Len = int(i.GetBufferSize())
return str
} }
type _IDXGIAdapter struct { type _IDXGIAdapter struct {

View File

@ -4,8 +4,6 @@ package gl
import ( import (
"fmt" "fmt"
"reflect"
"strings"
"unsafe" "unsafe"
) )
@ -14,7 +12,7 @@ import (
// //
// For example: // For example:
// //
// var data []uint8 // var data []byte
// ... // ...
// gl.TexImage2D(glconst.TEXTURE_2D, ..., glconst.UNSIGNED_BYTE, gl.Ptr(&data[0])) // gl.TexImage2D(glconst.TEXTURE_2D, ..., glconst.UNSIGNED_BYTE, gl.Ptr(&data[0]))
func Ptr(data any) unsafe.Pointer { func Ptr(data any) unsafe.Pointer {
@ -40,14 +38,3 @@ func Ptr(data any) unsafe.Pointer {
} }
return addr return addr
} }
// Str takes a null-terminated Go string and returns its GL-compatible address.
// This function reaches into Go string storage in an unsafe way so the caller
// must ensure the string is not garbage collected.
func Str(str string) *uint8 {
if !strings.HasSuffix(str, "\x00") {
panic("str argument missing null terminator: " + str)
}
header := (*reflect.StringHeader)(unsafe.Pointer(&str))
return (*uint8)(unsafe.Pointer(header.Data))
}

View File

@ -13,7 +13,7 @@ import "C"
// GoStr takes a null-terminated string returned by OpenGL and constructs a // GoStr takes a null-terminated string returned by OpenGL and constructs a
// corresponding Go string. // corresponding Go string.
func GoStr(cstr *uint8) string { func GoStr(cstr *byte) string {
return C.GoString((*C.char)(unsafe.Pointer(cstr))) return C.GoString((*C.char)(unsafe.Pointer(cstr)))
} }
@ -24,18 +24,18 @@ func GoStr(cstr *uint8) string {
// in order to free the memory. // in order to free the memory.
// //
// If no strings are provided as a parameter this function will panic. // If no strings are provided as a parameter this function will panic.
func Strs(strs ...string) (cstrs **uint8, free func()) { func Strs(strs ...string) (cstrs **byte, free func()) {
if len(strs) == 0 { if len(strs) == 0 {
panic("Strs: expected at least 1 string") panic("gl: expected at least 1 string at Strs")
} }
css := make([]*uint8, 0, len(strs)) css := make([]*byte, 0, len(strs))
for _, str := range strs { for _, str := range strs {
cs := C.CString(str) cs := C.CString(str)
css = append(css, (*uint8)(unsafe.Pointer(cs))) css = append(css, (*byte)(unsafe.Pointer(cs)))
} }
return (**uint8)(&css[0]), func() { return (**byte)(&css[0]), func() {
for _, cs := range css { for _, cs := range css {
C.free(unsafe.Pointer(cs)) C.free(unsafe.Pointer(cs))
} }

View File

@ -6,22 +6,24 @@ package gl
import ( import (
"runtime" "runtime"
"strings"
"unsafe" "unsafe"
) )
// GoStr takes a null-terminated string returned by OpenGL and constructs a // GoStr takes a null-terminated string returned by OpenGL and constructs a
// corresponding Go string. // corresponding Go string.
func GoStr(cstr *uint8) string { func GoStr(cstr *byte) string {
str := "" if cstr == nil {
for { return ""
if *cstr == 0 {
break
}
str += string(*cstr)
cstr = (*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(cstr)) + 1))
} }
return str x := unsafe.Slice(cstr, 1e9)
for i, c := range x {
if c == 0 {
str := make([]byte, i)
copy(str, x[:i])
return string(str)
}
}
return ""
} }
// Strs takes a list of Go strings (with or without null-termination) and // Strs takes a list of Go strings (with or without null-termination) and
@ -31,19 +33,20 @@ func GoStr(cstr *uint8) string {
// in order to free the memory. // in order to free the memory.
// //
// If no strings are provided as a parameter this function will panic. // If no strings are provided as a parameter this function will panic.
func Strs(strs ...string) (cstrs **uint8, free func()) { func Strs(strs ...string) (cstrs **byte, free func()) {
if len(strs) == 0 { if len(strs) == 0 {
panic("Strs: expected at least 1 string") panic("gl: expected at least 1 string at Strs")
} }
var pinned []string pinned := make([][]byte, 0, len(strs))
var ptrs []*uint8 ptrs := make([]*byte, 0, len(strs))
for _, str := range strs { for _, str := range strs {
if !strings.HasSuffix(str, "\x00") { bs := []byte(str)
str += "\x00" if len(bs) == 0 || bs[len(bs)-1] != 0 {
bs = append(bs, 0)
} }
pinned = append(pinned, str) pinned = append(pinned, bs)
ptrs = append(ptrs, Str(str)) ptrs = append(ptrs, &bs[0])
} }
return &ptrs[0], func() { return &ptrs[0], func() {