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

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -