Added function generation to zwinconstgen.go. cgo uses DWARF to get function parameters, so we'll just specify them manually ourselves; see funcnames_windows.go.
This commit is contained in:
parent
06c2f1b051
commit
c55386f929
|
@ -0,0 +1,6 @@
|
|||
// 11 july 2014
|
||||
|
||||
package ui
|
||||
|
||||
// wfunc kernel32 GetModuleHandleW *uint16 uintptr
|
||||
// wfunc kernel32 GetStartupInfoW *s_STARTUPINFOW void
|
|
@ -15,8 +15,8 @@ var (
|
|||
)
|
||||
|
||||
func getWinMainParams() (err error) {
|
||||
hInstance, err = f_GetModuleHandle(nil)
|
||||
if err != nil {
|
||||
hInstance, err = f_GetModuleHandleW(nil)
|
||||
if hInstance == 0 {
|
||||
return fmt.Errorf("error getting hInstance: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ func getPackage(path string) (pkg *ast.Package) {
|
|||
filter := func(i os.FileInfo) bool {
|
||||
return strings.HasSuffix(i.Name(), "_windows.go")
|
||||
}
|
||||
pkgs, err := parser.ParseDir(fileset, path, filter, parser.AllErrors)
|
||||
pkgs, err := parser.ParseDir(fileset, path, filter, parser.AllErrors | parser.ParseComments)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -57,8 +57,6 @@ func (w *walker) Visit(node ast.Node) ast.Visitor {
|
|||
unknown[n.Name] = struct{}{}
|
||||
}
|
||||
}
|
||||
case *ast.Comment: // function?
|
||||
// TODO
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
@ -72,9 +70,101 @@ func gatherNames(pkg *ast.Package) {
|
|||
for _, d := range f.Decls {
|
||||
ast.Walk(&walker{desired}, d)
|
||||
}
|
||||
for _, c := range f.Comments {
|
||||
for _, cc := range c.List {
|
||||
readComment(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var funcs []string
|
||||
var dlls = map[string]struct{}{}
|
||||
|
||||
// parse comments of the form "// wfunc dll Name argtypes {ret[,noerr]|void}"
|
||||
// TODO clean this up
|
||||
func readComment(c *ast.Comment) {
|
||||
words := strings.Split(c.Text, " ")[1:] // strip leading //
|
||||
if len(words) <= 0 || words[0] != "wfunc" {
|
||||
return
|
||||
}
|
||||
dll := words[1]
|
||||
dlls[dll] = struct{}{}
|
||||
name := words[2]
|
||||
args := make([]string, 0, len(words))
|
||||
for i := 3; i < len(words) - 1; i++ {
|
||||
args = append(args, words[i])
|
||||
}
|
||||
ret := words[len(words) - 1]
|
||||
|
||||
funcs = append(funcs, fmt.Sprintf("var fv_%s = %s.NewProc(%q)", name, dll, name))
|
||||
|
||||
r1 := "r1"
|
||||
err := "err"
|
||||
assign := ":="
|
||||
|
||||
r := rune('a')
|
||||
argspec := ""
|
||||
for _, t := range args {
|
||||
argspec += fmt.Sprintf("%c %s, ", r, t)
|
||||
r++
|
||||
}
|
||||
retspec := ""
|
||||
if ret != "void" {
|
||||
r := strings.Split(ret, ",")
|
||||
retspec = "(" + r[0]
|
||||
if len(r) > 1 && r[1] == "noerr" {
|
||||
err = "_"
|
||||
} else {
|
||||
retspec += ", error"
|
||||
}
|
||||
retspec += ")"
|
||||
} else {
|
||||
r1 = "_"
|
||||
err = "_"
|
||||
assign = "="
|
||||
}
|
||||
funcs = append(funcs, fmt.Sprintf("func f_%s(%s) %s {", name, argspec, retspec))
|
||||
|
||||
call := fmt.Sprintf("\t%s, _, %s %s fv_%s.Call(", r1, err, assign, name)
|
||||
r = rune('a')
|
||||
for _, t := range args {
|
||||
call += "uintptr("
|
||||
if t[0] == '*' {
|
||||
call += "unsafe.Pointer("
|
||||
}
|
||||
call += fmt.Sprintf("%c", r)
|
||||
if t[0] == '*' {
|
||||
call += ")"
|
||||
}
|
||||
call += "), "
|
||||
r++
|
||||
}
|
||||
call += ")"
|
||||
funcs = append(funcs, call)
|
||||
|
||||
if ret != "void" {
|
||||
r := strings.Split(ret, ",")
|
||||
retspec = "return (" + r[0] + ")("
|
||||
if r[0][0] == '*' {
|
||||
retspec += "unsafe.Pointer("
|
||||
}
|
||||
retspec += "r1"
|
||||
if r[0][0] == '*' {
|
||||
retspec += ")"
|
||||
}
|
||||
retspec += ")"
|
||||
if len(r) > 1 && r[1] == "noerr" {
|
||||
// do nothing
|
||||
} else {
|
||||
retspec += ", err"
|
||||
}
|
||||
funcs = append(funcs, retspec)
|
||||
}
|
||||
|
||||
funcs = append(funcs, "}")
|
||||
}
|
||||
|
||||
// for backwards compatibiilty reasons, Windows defines GetWindowLongPtr()/SetWindowLongPtr() as a macro which expands to GetWindowLong()/SetWindowLong() on 32-bit systems
|
||||
// we'll just simulate that here
|
||||
var gwlpNames = map[string]string{
|
||||
|
@ -82,10 +172,6 @@ var gwlpNames = map[string]string{
|
|||
"amd64": "etWindowLongPtrW",
|
||||
}
|
||||
|
||||
func writeLine(f *os.File, line string) {
|
||||
fmt.Fprintf(f, "%s\n", line)
|
||||
}
|
||||
|
||||
const outTemplate = `package main
|
||||
import (
|
||||
"fmt"
|
||||
|
@ -108,7 +194,7 @@ import (
|
|||
// #include <commctrl.h>
|
||||
// #include <stdint.h>
|
||||
{{range .Consts}}// uintptr_t {{.}} = (uintptr_t) ({{noprefix .}});
|
||||
{{end}}import "C"
|
||||
{{end}}import "C" // notice the lack of newline in the template
|
||||
// MinGW will generate handle pointers as pointers to some structure type under some conditions I don't fully understand; here's full overrides
|
||||
var handleOverrides = []string{
|
||||
"HWND",
|
||||
|
@ -148,8 +234,16 @@ func winName(t reflect.Type) string {
|
|||
func main() {
|
||||
buf := new(bytes.Buffer)
|
||||
fmt.Fprintln(buf, "package ui")
|
||||
fmt.Fprintln(buf, "import (")
|
||||
fmt.Fprintln(buf, "\t\"syscall\"")
|
||||
fmt.Fprintln(buf, "\t\"unsafe\"")
|
||||
fmt.Fprintln(buf, ")")
|
||||
|
||||
// constants
|
||||
{{range .Consts}} fmt.Fprintf(buf, "const %s = %d\n", {{printf "%q" .}}, C.{{.}})
|
||||
{{end}}
|
||||
|
||||
// structures
|
||||
var t reflect.Type
|
||||
{{range .Structs}} t = reflect.TypeOf(C.{{noprefix .}}{})
|
||||
fmt.Fprintf(buf, "type %s struct {\n", {{printf "%q" .}})
|
||||
|
@ -166,6 +260,14 @@ func main() {
|
|||
fmt.Fprintf(buf, "type t_LPARAM %s\n", winName(reflect.TypeOf(C.LPARAM(0))))
|
||||
fmt.Fprintf(buf, "type t_LRESULT %s\n", winName(reflect.TypeOf(C.LRESULT(0))))
|
||||
|
||||
// functions
|
||||
{{range .Funcs}} fmt.Fprintf(buf, "%s\n", {{printf "%q" .}})
|
||||
{{end}}
|
||||
|
||||
// DLLs
|
||||
{{range .DLLs}} fmt.Fprintf(buf, "var %s = syscall.NewLazyDLL(%q)\n", {{printf "%q" .}}, {{printf "%s.dll" . | printf "%q"}})
|
||||
{{end}}
|
||||
|
||||
// and finally done
|
||||
res, err := format.Source(buf.Bytes())
|
||||
if err != nil { panic(err.Error() + "\n" + string(buf.Bytes())) }
|
||||
|
@ -176,6 +278,8 @@ func main() {
|
|||
type templateArgs struct {
|
||||
Consts []string
|
||||
Structs []string
|
||||
Funcs []string
|
||||
DLLs []string
|
||||
}
|
||||
|
||||
var templateFuncs = template.FuncMap{
|
||||
|
@ -213,6 +317,7 @@ func main() {
|
|||
// keep sorted for git
|
||||
consts := make([]string, 0, len(unknown))
|
||||
structs := make([]string, 0, len(unknown))
|
||||
sorteddlls := make([]string, 0, len(dlls))
|
||||
for ident, _ := range unknown {
|
||||
if strings.HasPrefix(ident, "s_") {
|
||||
structs = append(structs, ident)
|
||||
|
@ -220,8 +325,12 @@ func main() {
|
|||
}
|
||||
consts = append(consts, ident)
|
||||
}
|
||||
for dll, _ := range dlls {
|
||||
sorteddlls = append(sorteddlls, dll)
|
||||
}
|
||||
sort.Strings(consts)
|
||||
sort.Strings(structs)
|
||||
sort.Strings(sorteddlls)
|
||||
|
||||
// thanks to james4k in irc.freenode.net/#go-nuts
|
||||
tmpdir, err := ioutil.TempDir("", "windowsconstgen")
|
||||
|
@ -238,6 +347,8 @@ func main() {
|
|||
err = t.Execute(f, &templateArgs{
|
||||
Consts: consts,
|
||||
Structs: structs,
|
||||
Funcs: funcs,
|
||||
DLLs: sorteddlls,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
Loading…
Reference in New Issue