c - What are the sign extension rules for calling Windows API functions (stdcall)? This is needed to call WInAPI from Go, which is strict about int types -
oops, there 1 thing forgot when made this answer, , it's i'm both not quite sure on myself , can't seem find information on msdn , google , stack overflow search.
there number of places in windows api use negative number, or number large fit in signed integer; instance, cw_usedefault
, invalid_handle_value
, gwlp_userdata
, , on. in world of c, fine , dandy: language's integer promotion rules come rescue.
but in go, have pass arguments functions uintptr
(which equivalent c's uintptr_t
). return value function returned way, , need compare. go doesn't allow integer promotion, , doesn't allow convert signed constant expression unsigned 1 @ compile-time.
right now, have bit of jerry-rig set handling these constants in ui library. (here's example of solution looks in action.) however, i'm not quite satisfied solution; feels me it's assuming things abi, , want absolutely sure of i'm doing.
so question is: how signed values handled when passing them windows api functions , how handled when returning?
all constants autogenerated (example output). autogenerator uses a c ffi, i'd rather not use main project since can call dlls directly (this makes cross-compilation easier @ least rest of year). if somehow leverage that, instance making c-side variable of form
uintptr_t x_const_name = (uintptr_t) (const_name);
that helpful. can't without answer.
thanks!
update
someone on irc put differently (reformatted avoid horizontal scrolling):
[19:13] <fragag> basically, you're asking whether int value of -1 returned 0x00000000ffffffff or 0xffffffffffffffff if int 4 bytes , uintptr 8 bytes
basically this, windows api interop, parameters passed in, , regardless of uintptr size.
@twotwotwo's comments question pointed me in right direction. if stack overflow allowed marking comments answers , having multiple answers marked, i'd that.
tl;dr version: have correct after all.
i wrote program (below) dumped constants package syscall , looked constants negative, not == -1 (as ^0
). standard file handles (std_error_handle
, std_input_handle
, , std_output_handle
) (-12, -10, , -11, respectively). code in package syscall passes these constants sole argument of getstdhandle(h int)
, produces required file handle package os. getstdhandle()
passes int autogenerated function getstdhandle(stdhandle int)
wraps call getstdhandle()
system call. getstdhandle()
takes int , merely converts uintptr
passing syscall.syscall()
. though no explanation given in autogenerator's source (mksyscall_windows.go), if didn't work, neither fmt.println()
=p
all of above identical on both windows/386 , windows/amd64; thing in processor-specific file getstdhandle()
, relevant code identical.
my negconst()
function doing same thing, more directly. such, can safely assume correct.
thanks!
// 4 june 2014 // based on code 24 may 2014 package main import ( "fmt" "os" "strings" "go/token" "go/ast" "go/parser" "code.google.com/p/go.tools/go/types" _ "code.google.com/p/go.tools/go/gcimporter" ) var arch string func getpackage(path string) (typespkg *types.package, pkginfo types.info) { var pkg *ast.package fileset := token.newfileset() // parser.parsedir() writes this; not sure why doesn't return 1 instead filter := func(i os.fileinfo) bool { if strings.contains(i.name(), "_windows") && strings.contains(i.name(), "_" + arch) && strings.hassuffix(i.name(), ".go") { return true } if i.name() == "race.go" || // skip these i.name() == "flock.go" { return false } return strings.hassuffix(i.name(), "_windows.go") || (!strings.contains(i.name(), "_")) } pkgs, err := parser.parsedir(fileset, path, filter, parser.allerrors) if err != nil { panic(err) } k, _ := range pkgs { // sole key if pkgs[k].name == "syscall" { pkg = pkgs[k] break } } if pkg == nil { panic("package syscall not found") } // can't pass pkg.files directly types.check() because former map , latter slice ff := make([]*ast.file, 0, len(pkg.files)) _, v := range pkg.files { ff = append(ff, v) } // if don't make() each map, package types won't fill structure pkginfo.defs = make(map[*ast.ident]types.object) pkginfo.scopes = make(map[ast.node]*types.scope) typespkg, err = new(types.config).check(path, fileset, ff, &pkginfo) if err != nil { panic(err) } return typespkg, pkginfo } func main() { pkgpath := "/home/pietro/go/src/pkg/syscall" arch = os.args[1] pkg, _ := getpackage(pkgpath) scope := pkg.scope() _, name := range scope.names() { obj := scope.lookup(name) if obj == nil { panic(fmt.errorf("nil object %q scope %v", name, scope)) } if !obj.exported() { // exported names continue } if _, ok := obj.(*types.const); ok { fmt.printf("egrep -rh '#define[ ]+%s' ~/winshare/include/ 2>/dev/null\n", obj.name()) } // otherwise skip } }
Comments
Post a Comment