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) {
|
func getWinMainParams() (err error) {
|
||||||
hInstance, err = f_GetModuleHandle(nil)
|
hInstance, err = f_GetModuleHandleW(nil)
|
||||||
if err != nil {
|
if hInstance == 0 {
|
||||||
return fmt.Errorf("error getting hInstance: %v", err)
|
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 {
|
filter := func(i os.FileInfo) bool {
|
||||||
return strings.HasSuffix(i.Name(), "_windows.go")
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,6 @@ func (w *walker) Visit(node ast.Node) ast.Visitor {
|
||||||
unknown[n.Name] = struct{}{}
|
unknown[n.Name] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case *ast.Comment: // function?
|
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
@ -72,9 +70,101 @@ func gatherNames(pkg *ast.Package) {
|
||||||
for _, d := range f.Decls {
|
for _, d := range f.Decls {
|
||||||
ast.Walk(&walker{desired}, d)
|
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
|
// 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
|
// we'll just simulate that here
|
||||||
var gwlpNames = map[string]string{
|
var gwlpNames = map[string]string{
|
||||||
|
@ -82,10 +172,6 @@ var gwlpNames = map[string]string{
|
||||||
"amd64": "etWindowLongPtrW",
|
"amd64": "etWindowLongPtrW",
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeLine(f *os.File, line string) {
|
|
||||||
fmt.Fprintf(f, "%s\n", line)
|
|
||||||
}
|
|
||||||
|
|
||||||
const outTemplate = `package main
|
const outTemplate = `package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -108,7 +194,7 @@ import (
|
||||||
// #include <commctrl.h>
|
// #include <commctrl.h>
|
||||||
// #include <stdint.h>
|
// #include <stdint.h>
|
||||||
{{range .Consts}}// uintptr_t {{.}} = (uintptr_t) ({{noprefix .}});
|
{{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
|
// 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{
|
var handleOverrides = []string{
|
||||||
"HWND",
|
"HWND",
|
||||||
|
@ -148,8 +234,16 @@ func winName(t reflect.Type) string {
|
||||||
func main() {
|
func main() {
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
fmt.Fprintln(buf, "package ui")
|
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.{{.}})
|
{{range .Consts}} fmt.Fprintf(buf, "const %s = %d\n", {{printf "%q" .}}, C.{{.}})
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
// structures
|
||||||
var t reflect.Type
|
var t reflect.Type
|
||||||
{{range .Structs}} t = reflect.TypeOf(C.{{noprefix .}}{})
|
{{range .Structs}} t = reflect.TypeOf(C.{{noprefix .}}{})
|
||||||
fmt.Fprintf(buf, "type %s struct {\n", {{printf "%q" .}})
|
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_LPARAM %s\n", winName(reflect.TypeOf(C.LPARAM(0))))
|
||||||
fmt.Fprintf(buf, "type t_LRESULT %s\n", winName(reflect.TypeOf(C.LRESULT(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
|
// and finally done
|
||||||
res, err := format.Source(buf.Bytes())
|
res, err := format.Source(buf.Bytes())
|
||||||
if err != nil { panic(err.Error() + "\n" + string(buf.Bytes())) }
|
if err != nil { panic(err.Error() + "\n" + string(buf.Bytes())) }
|
||||||
|
@ -176,6 +278,8 @@ func main() {
|
||||||
type templateArgs struct {
|
type templateArgs struct {
|
||||||
Consts []string
|
Consts []string
|
||||||
Structs []string
|
Structs []string
|
||||||
|
Funcs []string
|
||||||
|
DLLs []string
|
||||||
}
|
}
|
||||||
|
|
||||||
var templateFuncs = template.FuncMap{
|
var templateFuncs = template.FuncMap{
|
||||||
|
@ -213,6 +317,7 @@ func main() {
|
||||||
// keep sorted for git
|
// keep sorted for git
|
||||||
consts := make([]string, 0, len(unknown))
|
consts := make([]string, 0, len(unknown))
|
||||||
structs := make([]string, 0, len(unknown))
|
structs := make([]string, 0, len(unknown))
|
||||||
|
sorteddlls := make([]string, 0, len(dlls))
|
||||||
for ident, _ := range unknown {
|
for ident, _ := range unknown {
|
||||||
if strings.HasPrefix(ident, "s_") {
|
if strings.HasPrefix(ident, "s_") {
|
||||||
structs = append(structs, ident)
|
structs = append(structs, ident)
|
||||||
|
@ -220,8 +325,12 @@ func main() {
|
||||||
}
|
}
|
||||||
consts = append(consts, ident)
|
consts = append(consts, ident)
|
||||||
}
|
}
|
||||||
|
for dll, _ := range dlls {
|
||||||
|
sorteddlls = append(sorteddlls, dll)
|
||||||
|
}
|
||||||
sort.Strings(consts)
|
sort.Strings(consts)
|
||||||
sort.Strings(structs)
|
sort.Strings(structs)
|
||||||
|
sort.Strings(sorteddlls)
|
||||||
|
|
||||||
// thanks to james4k in irc.freenode.net/#go-nuts
|
// thanks to james4k in irc.freenode.net/#go-nuts
|
||||||
tmpdir, err := ioutil.TempDir("", "windowsconstgen")
|
tmpdir, err := ioutil.TempDir("", "windowsconstgen")
|
||||||
|
@ -238,6 +347,8 @@ func main() {
|
||||||
err = t.Execute(f, &templateArgs{
|
err = t.Execute(f, &templateArgs{
|
||||||
Consts: consts,
|
Consts: consts,
|
||||||
Structs: structs,
|
Structs: structs,
|
||||||
|
Funcs: funcs,
|
||||||
|
DLLs: sorteddlls,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
Loading…
Reference in New Issue