-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove Cgo dependency on Windows #102
Changes from all commits
09b7832
82c14b3
5e0daf8
11618d0
cabcdf4
8f47bcd
b844e0e
ecaf743
97a0597
471a800
2143010
522711e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,9 @@ | ||
package main | ||
|
||
import "fmt" | ||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
// A Function definition. | ||
type Function struct { | ||
|
@@ -10,6 +13,33 @@ type Function struct { | |
Return Type | ||
} | ||
|
||
// IsImplementedForSyscall reports whether the function is implemented for syscall or not. | ||
func (f Function) IsImplementedForSyscall() bool { | ||
// TODO: Use syscall.Syscall18 when Go 1.12 is the minimum supported version. | ||
if len(f.Parameters) > 15 { | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
// Syscall returns a syscall expression for Windows. | ||
func (f Function) Syscall() string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this would be more idiomatic/clear if it returned an error when !IsImplementedForSyscall (rather than having a separate func that needs to be called)? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is called at templates to generate |
||
var ps []string | ||
for _, p := range f.Parameters { | ||
ps = append(ps, p.Type.ConvertGoToUintptr(p.GoName())) | ||
} | ||
for len(ps) == 0 || len(ps)%3 != 0 { | ||
ps = append(ps, "0") | ||
} | ||
|
||
post := "" | ||
if len(ps) > 3 { | ||
post = fmt.Sprintf("%d", len(ps)) | ||
} | ||
|
||
return fmt.Sprintf("syscall.Syscall%s(gp%s, %d, %s)", post, f.GoName, len(f.Parameters), strings.Join(ps, ", ")) | ||
} | ||
|
||
// A Parameter to a Function. | ||
type Parameter struct { | ||
Name string | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,14 +69,32 @@ func (pkg *Package) GeneratePackage(dir string) error { | |
if err := pkg.generateFile("package", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("package_notwindows", dir); err != nil { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having all these files is super unfortunate, but I'm not sure whether there is anything to be done for it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps something like:
|
||
return err | ||
} | ||
if err := pkg.generateFile("package_windows", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("conversions", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("procaddr", dir); err != nil { | ||
if err := pkg.generateFile("conversions_notwindows", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("conversions_windows", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("procaddr_notwindows", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("procaddr_windows", dir); err != nil { | ||
return err | ||
} | ||
if pkg.HasDebugCallbackFeature() { | ||
if err := pkg.generateFile("debug", dir); err != nil { | ||
if err := pkg.generateFile("debug_notwindows", dir); err != nil { | ||
return err | ||
} | ||
if err := pkg.generateFile("debug_windows", dir); err != nil { | ||
return err | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
//glow:keepspace | ||
// +build !windows | ||
|
||
// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. | ||
|
||
package {{.Name}} | ||
|
||
import ( | ||
"reflect" | ||
"unsafe" | ||
) | ||
|
||
// #include <stdlib.h> | ||
import "C" | ||
|
||
// GoStr takes a null-terminated string returned by OpenGL and constructs a | ||
// corresponding Go string. | ||
func GoStr(cstr *uint8) string { | ||
return C.GoString((*C.char)(unsafe.Pointer(cstr))) | ||
} | ||
|
||
// Strs takes a list of Go strings (with or without null-termination) and | ||
// returns their C counterpart. | ||
// | ||
// The returned free function must be called once you are done using the strings | ||
// in order to free the memory. | ||
// | ||
// If no strings are provided as a parameter this function will panic. | ||
func Strs(strs ...string) (cstrs **uint8, free func()) { | ||
if len(strs) == 0 { | ||
panic("Strs: expected at least 1 string") | ||
} | ||
|
||
// Allocate a contiguous array large enough to hold all the strings' contents. | ||
n := 0 | ||
for i := range strs { | ||
n += len(strs[i]) | ||
} | ||
data := C.malloc(C.size_t(n)) | ||
|
||
// Copy all the strings into data. | ||
dataSlice := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ | ||
Data: uintptr(data), | ||
Len: n, | ||
Cap: n, | ||
})) | ||
css := make([]*uint8, len(strs)) // Populated with pointers to each string. | ||
offset := 0 | ||
for i := range strs { | ||
copy(dataSlice[offset:offset+len(strs[i])], strs[i][:]) // Copy strs[i] into proper data location. | ||
css[i] = (*uint8)(unsafe.Pointer(&dataSlice[offset])) // Set a pointer to it. | ||
offset += len(strs[i]) | ||
} | ||
|
||
return (**uint8)(&css[0]), func() { C.free(data) } | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
//glow:keepspace | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not clear to me why this conversion code, or the debug code, needs to be forked across Windows/not-Windows. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #102 (comment) is the reason: using this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any way we can reduce the duplication by factoring out the parts that are the same? (Or am I misreading and all the implementations are subtly different?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done (created the common There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getting back to this now (finally, sorry for the delay)...
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Quick reply: go-gl/gl#80 might be related, but I am not sure. I'll take a look later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like if we can make conversions.tmpl pure Go first, we should do this before merging this PR. Wdyt? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I'm all for updating conversions to work across the board. |
||
// +build windows | ||
|
||
// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. | ||
|
||
package {{.Name}} | ||
|
||
import ( | ||
"runtime" | ||
"strings" | ||
"unsafe" | ||
) | ||
|
||
// GoStr takes a null-terminated string returned by OpenGL and constructs a | ||
// corresponding Go string. | ||
func GoStr(cstr *uint8) string { | ||
str := "" | ||
for { | ||
if *cstr == 0 { | ||
break | ||
} | ||
str += string(*cstr) | ||
cstr = (*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(cstr)) + 1)) | ||
} | ||
return str | ||
} | ||
|
||
// Strs takes a list of Go strings (with or without null-termination) and | ||
// returns their C counterpart. | ||
// | ||
// The returned free function must be called once you are done using the strings | ||
// in order to free the memory. | ||
// | ||
// If no strings are provided as a parameter this function will panic. | ||
func Strs(strs ...string) (cstrs **uint8, free func()) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @errcw My concern was that There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm so sorry for the slow responses here. The amount of free time I have is vanishingly small these days. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for responding! Our plan is to make this function in pure Go (no cgo in any environment), right? If so, we would not be able to use C allocator. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, right, of course. So I'm clear, on Windows, we're using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, there is no warning, and we can assure the lifetime of the objects (by
This is unsafe, and unfortunately Go runtime suspends the execution with warning messages. That's the problem. Then, I think it would be inevitable to split the implementation for Windows and non-Windows. My suggestion is to split the allocation part to minimize the split code. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
So, you are fine with splitting the code? :-) |
||
if len(strs) == 0 { | ||
panic("Strs: expected at least 1 string") | ||
} | ||
|
||
var pinned []string | ||
var ptrs []*uint8 | ||
for _, str := range strs { | ||
if !strings.HasSuffix(str, "\x00") { | ||
str += "\x00" | ||
} | ||
pinned = append(pinned, str) | ||
ptrs = append(ptrs, Str(str)) | ||
} | ||
|
||
return &ptrs[0], func() { | ||
runtime.KeepAlive(pinned) | ||
pinned = nil | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
//glow:keepspace | ||
// Code generated by glow (https://github.com/go-gl/glow). DO NOT EDIT. | ||
|
||
package {{.Name}} | ||
//glow:rmspace | ||
|
||
import "unsafe" | ||
|
||
type DebugProc func( | ||
source uint32, | ||
gltype uint32, | ||
id uint32, | ||
severity uint32, | ||
length int32, | ||
message string, | ||
userParam unsafe.Pointer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like Go 1.12 is the lowest supported version now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At least in glow. The gl package's mod file still says 1.9. Also, in 1.18 all the syscall functions except SyscallN are deprecated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, go-gl/gl#144