【问题标题】:Issue with sys package related to I/O operation与 I/O 操作相关的 sys 包问题
【发布时间】:2021-05-16 05:48:01
【问题描述】:

因为我想使用 CreateFile 函数访问一些较低级别的 API 来执行 I/O 操作 syscall.CreateFile( name *uint16…) 这样做时我面临一个问题,名称参数是 *uint16 但它应该是一个数组 ([]uint16) 以便它可以处理 UTF-16 格式的字符串。正如我们在 Microsoft 提供的示例中看到的那样 -> link 其中TEXT 宏将字符串转换为 wchar_t 数组,或者我们可以说 []uint16。

提前谢谢,如果我说错了,我只是这个领域的蹒跚学步的孩子。

(解决方案 1) func UTF16PtrFromString(s string) (*uint16, error) 内置编码器,返回指向 UTF-16 编码的指针

(解决方案 2) 因为之前我不知道解决方案 1,所以我编写了自己的函数来完成确切的工作,因此您可以忽略此解决方案

为了将文件名(字符串)传递给 sys 包,我们必须首先将字符串转换为 UTF-16 数组并传递第一个元素的指针

var srcUTf16 [ ]uint16 = utf16.Encode([ ]rune(src+ "\x00"))
syscall.CreateFile(&srcUTf16[0],..... )
  1. 编辑:-添加解决方案
  2. 编辑:- 添加正确的解决方案并在解决方案 2 中添加终止 NUL。

【问题讨论】:

  • []uint16 不是一个数组,它是一个切片,不能传递给系统调用。参数与 C 中的参数相同。
  • 你有什么问题?
  • 关于您的编辑,x/sys/windows 包有一个 UTF16PtrFromString 函数可以正确编码。您的版本缺少终止的 null。
  • @JimB 感谢您的纠正。刚来这里是为了纠正我的错误,因为有人在另一个论坛中指出了同样的错误,然后看到了你的评论????顺便说一句

标签: windows go io


【解决方案1】:

我并不关心 Go 生成的 Windows API 函数签名,我有 written about this。所以如果你愿意,你可以自己写。制作一个这样的文件:

//go:generate mkwinsyscall -output zfile.go file.go
//sys createFile(name string, access int, mode int, sec *windows.SecurityAttributes, disp int, flag int, template int) (hand int, err error) = kernel32.CreateFileW
package main
import "golang.org/x/sys/windows"

func main() {
   n, e := createFile(
      "file.txt",
      windows.GENERIC_READ,
      0,
      nil,
      windows.CREATE_NEW,
      windows.FILE_ATTRIBUTE_NORMAL,
      0,
   )
   if e != nil {
      panic(e)
   }
   println(n)
}

然后构建:

go mod init file
go generate
go mod tidy
go build

我知道结果有效,因为它第一次返回有效句柄,第二次返回无效句柄(当然也因为创建了文件):

PS C:\> .\file.exe
336
PS C:\> .\file.exe
-1

如果需要,您可以编辑我在上面放置的签名行,以满足您的需要。

【讨论】:

  • 不错,你说得对,根据 Go 团队编写的神秘签名,任何人都很难理解和编写。
猜你喜欢
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 2015-10-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
相关资源
最近更新 更多