如何在 Go 中使用 Win32 的 GetRawInputDeviceList?

我正在尝试GetRawInputDeviceList在 Go 中使用该函数,但我不断收到以下错误:

The parameter is incorrect.

根据官方文档:第一个参数需要是RAWINPUTDEVICELIST连接到系统的设备的结构数组。我不太明白要unsafe.Pointer使其正常工作,我需要做什么、指针算术(?)和其他事情的组合。

我发现这篇 Medium 文章提供了一些指导,但它并不直接适用于我的用例。我没有足够的使用指针和手动内存管理的经验来将其应用于我的问题。我不知道如何将这个 C++ 示例转换为 Go,我非常绝望,以至于我试图将一个有效的 VBA 解决方案转换为 Go,但没有成功。

关于这个问题,我有两个问题:

  1. 如何将 Go 中的结构数组转换为 Windows API 调用所需的适当类型?

  2. 如何将 Windows API 调用的结果转换回具有填充数据的结构数组?

环境

这是我的系统/语言详细信息:

  • macOS Mojave v10.14.6

  • Go v1.10.7(需要在 Windows XP 上运行可执行文件)

我的目标是 Windows XP,所以我运行以下命令来编译它:

env GOOS=windows GOARCH=386 go1.10.7 build -o example.exe example.go

代码

这是我试图开始工作的代码。我还没有做任何事情devices,但目标是使用句柄(DeviceHandlefrom rawInputDeviceList)来获取有关输入设备的信息。

package main


import (

  "fmt"

  "syscall"

  "unsafe"

)


// RAWINPUTDEVICELIST structure

type rawInputDeviceList struct {

  DeviceHandle uintptr

  Type         uint32

}


var (

  user32 = syscall.NewLazyDLL("user32.dll")

  getRawInputDeviceListProc = user32.NewProc("GetRawInputDeviceList")

)


func main() {

  dl := rawInputDeviceList{}

  size := uint32(unsafe.Sizeof(dl))


  // First I determine how many input devices are on the system, which

  // gets assigned to `devCount`

  var devCount uint32

  _ = getRawInputDeviceList(nil, &devCount, size)


  if devCount > 0 {

    size = size * devCount

    devices := make([]rawInputDeviceList, size) // <- This is definitely wrong


    for i := 0; i < int(devCount); i++ {

      devices[i] = rawInputDeviceList{}

    }


    // Here is where I get the "The parameter is incorrect." error:

    err := getRawInputDeviceList(&devices, &devCount, size)

    if err != nil {

      fmt.Printf("Error: %v", err)

    }

  }

}


// Enumerates the raw input devices attached to the system.

func getRawInputDeviceList(

  rawInputDeviceList *[]rawInputDeviceList, // <- This is probably wrong

  numDevices *uint32,

  size uint32,

) error {

  _, _, err := getRawInputDeviceListProc.Call(

    uintptr(unsafe.Pointer(rawInputDeviceList)),

    uintptr(unsafe.Pointer(numDevices)),

    uintptr(size))

  if err != syscall.Errno(0) {

    return err

  }


  return nil

}


德玛西亚99
浏览 226回答 1
1回答

红糖糍粑

首先,ERROR_INVALID_PARAMETER错误是由最后一个参数引起的:cbSize,根据文档,它应该始终设置为 size RAWINPUTDEVICELIST。然后您将通过编译器,但仍会收到运行时错误。因为你已经传递了一个数组指针。以下代码适用于我:package mainimport (&nbsp; "fmt"&nbsp; "syscall"&nbsp; "unsafe")// RAWINPUTDEVICELIST structuretype rawInputDeviceList struct {&nbsp; DeviceHandle uintptr&nbsp; Type&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;uint32}var (&nbsp; user32 = syscall.NewLazyDLL("user32.dll")&nbsp; getRawInputDeviceListProc = user32.NewProc("GetRawInputDeviceList"))func main() {&nbsp; dl := rawInputDeviceList{}&nbsp; size := uint32(unsafe.Sizeof(dl))&nbsp; // First I determine how many input devices are on the system, which&nbsp; // gets assigned to `devCount`&nbsp; var devCount uint32&nbsp; _ = getRawInputDeviceList(nil, &devCount, size)&nbsp; if devCount > 0 {&nbsp; &nbsp; devices := make([]rawInputDeviceList, size * devCount) // <- This is definitely wrong&nbsp; &nbsp; for i := 0; i < int(devCount); i++ {&nbsp; &nbsp; &nbsp; devices[i] = rawInputDeviceList{}&nbsp; &nbsp; }&nbsp; &nbsp; // Here is where I get the "The parameter is incorrect." error:&nbsp; &nbsp; err := getRawInputDeviceList(&devices[0], &devCount, size)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; fmt.Printf("Error: %v", err)&nbsp; &nbsp; }&nbsp; &nbsp; for i := 0; i < int(devCount); i++ {&nbsp; &nbsp; &nbsp; fmt.Printf("Type: %v", devices[i].Type)&nbsp; &nbsp; }&nbsp; }}// Enumerates the raw input devices attached to the system.func getRawInputDeviceList(&nbsp; rawInputDeviceList *rawInputDeviceList, // <- This is probably wrong&nbsp; numDevices *uint32,&nbsp; size uint32,) error {&nbsp; _, _, err := getRawInputDeviceListProc.Call(&nbsp; &nbsp; uintptr(unsafe.Pointer(rawInputDeviceList)),&nbsp; &nbsp; uintptr(unsafe.Pointer(numDevices)),&nbsp; &nbsp; uintptr(size))&nbsp; if err != syscall.Errno(0) {&nbsp; &nbsp; return err&nbsp; }&nbsp; return nil}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go