调用Windows API函数(stdcall)的符号扩展规则是什么?这需要从Go
哎呀,当我制作
this answer时,有一件事我忘记了,而且我对自己并不是很确定,而且我似乎无法在MSDN和Google以及Stack Overflow搜索中找到相关信息.
Windows API中有许多地方使用负数,或者数字太大而无法使用有符号整数;例如,CW_USEDEFAULT,INVALID_HANDLE_VALUE,GWLP_USERDATA等.在C的世界里,一切都很好,花花公子:语言的整数提升规则得到了拯救. 但在Go中,我必须将所有参数作为uintptr传递给函数(这相当于C的uintptr_t).函数的返回值也以这种方式返回,然后我需要进行比较. Go不允许整数提升,并且它不允许您在编译时将有符号常量表达式转换为无符号表达式. 现在,我在UI library中设置了bit of a jerry-rig用于处理这些常量.(Here’s an example of what this solution looks like in action.)但是,我对这个解决方案并不满意;我觉得它喜欢ABI的事情,我想要完全确定我在做什么. 所以我的问题是:将签名值传递给Windows API函数时如何处理?返回时如何处理? 我所有的常数都是autogenerated(example output).自动生成器使用a C ffi,我宁愿不用于主项目,因为我可以直接调用DLL(这也使得交叉编译至少在一年中的其他时间更容易).如果我可以以某种方式利用它,例如通过将所有内容都变成表单的C端变量 uintptr_t x_CONST_NAME = (uintptr_t) (CONST_NAME); 这会有所帮助.但如果没有这个答案我就不能这样做. 谢谢! 更新 IRC上的某个人将其改为不同(重新格式化以避免水平滚动): [19:13] <FraGag> basically,you're asking whether an int with a value of -1 will be returned as 0x00000000FFFFFFFF or as 0xFFFFFFFFFFFFFFFF if an int is 4 bytes and an uintptr is 8 bytes 基本上这个,但专门用于Windows API互操作,传入的参数,无论uintptr大小. 解决方法
@ twotwotwo对我的问题的评论指出了我正确的方向.如果Stack Overflow允许将注释标记为答案并标记多个答案,那么我会这样做.
tl; dr版本:毕竟我现在拥有的是正确的. 我编写了一个程序(下面),简单地从包syscall中转储所有常量,并查找负数但不是== -1的常量(因为它只是^ 0).标准文件句柄(STD_ERROR_HANDLE,STD_INPUT_HANDLE和STD_OUTPUT_HANDLE)分别为(-12,-10和-11).包syscall中的代码将这些常量作为getStdHandle(h int)的唯一参数传递,它为包os生成所需的文件句柄. getStdHandle()将此int传递给自动生成的函数GetStdHandle(stdhandle int),该函数包装对GetStdHandle()系统调用的调用. GetStdHandle()获取int并仅将其转换为uintptr以传入syscall.Syscall().虽然自动生成器的源代码(mksyscall_windows.go)没有给出解释,如果这不起作用,fmt.Println()= P也不会 所有上述内容在windows / 386和windows / amd64上都是相同的;处理器特定文件中唯一的东西是GetStdHandle(),但相关代码是相同的. 我的negConst()函数已经做了同样的事情,只是更直接.因此,我可以放心地认为它是正确的. 谢谢! // 4 june 2014 // based on code from 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() actually writes to this; not sure why it doesn't return one 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) } for k,_ := range pkgs { // get the sole key if pkgs[k].Name == "syscall" { pkg = pkgs[k] break } } if pkg == nil { panic("package syscall not found") } // we can't pass pkg.Files directly to types.Check() because the former is a map and the latter is a slice ff := make([]*ast.File,len(pkg.Files)) for _,v := range pkg.Files { ff = append(ff,v) } // if we don't make() each map,package types won't fill the 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() for _,name := range scope.Names() { obj := scope.Lookup(name) if obj == nil { panic(fmt.Errorf("nil object %q from scope %v",name,scope)) } if !obj.Exported() { // exported names only continue } if _,ok := obj.(*types.Const); ok { fmt.Printf("egrep -rh '#define[ ]+%s' ~/winshare/Include/ 2>/dev/nulln",obj.Name()) } // otherwise skip } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- Windows – 管理冗余/冲突组策略
- active-directory – 具有低用户权限的Active Directory管理
- windows-vista – 存储vista安装程序中所有用户共享的可写数
- 解决windows64位系统上安装mysql-python报错
- windows – 是否可以在防火墙后面安装一台机器并拥有公共IP
- windows – 在VBScript中获取命令行输出(无需写入文件)
- 在Windows 7 Home Basic上找不到IIS
- uint8的冗余强制转换不适用于GCC 4.8.1
- 在.net framework 4.0下运行.net framework 1.1程序
- 创建类似于本机Windows外观的Java GUI
- 是否可以将Windows Server 2016 Datacenter降级为
- Windows 下 mysql 5.7 设置 区分大小写(敏感),设
- windows-phone-8 – 在没有SD卡的Windows Phone
- 在win10上安装Linux系统安装
- windows-server-2003 – 在停用原始旧域控制器之
- 什么是好的,基于windows和iis(http)的分布式版本
- windows – 如何找出真正的屏幕刷新率(不是舍入的
- Windows – sox FAIL util:无法加载MAD解码器库
- windows-azure存储 – 任何方式为windows azure
- windows-server-2008 – 为什么捕获的异常会导致