为了账号安全,请及时绑定邮箱和手机立即绑定

如何在 Go 中使用 Win32 的 GetRawInputDeviceList?

如何在 Go 中使用 Win32 的 GetRawInputDeviceList?

Go
德玛西亚99 2022-05-23 14:58:31
我正在尝试GetRawInputDeviceList在 Go 中使用该函数,但我不断收到以下错误:The parameter is incorrect.根据官方文档:第一个参数需要是RAWINPUTDEVICELIST连接到系统的设备的结构数组。我不太明白要unsafe.Pointer使其正常工作,我需要做什么、指针算术(?)和其他事情的组合。我发现这篇 Medium 文章提供了一些指导,但它并不直接适用于我的用例。我没有足够的使用指针和手动内存管理的经验来将其应用于我的问题。我不知道如何将这个 C++ 示例转换为 Go,我非常绝望,以至于我试图将一个有效的 VBA 解决方案转换为 Go,但没有成功。关于这个问题,我有两个问题:如何将 Go 中的结构数组转换为 Windows API 调用所需的适当类型?如何将 Windows API 调用的结果转换回具有填充数据的结构数组?环境这是我的系统/语言详细信息:macOS Mojave v10.14.6Go 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 mainimport (  "fmt"  "syscall"  "unsafe")// RAWINPUTDEVICELIST structuretype 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}
查看完整描述

1 回答

?
红糖糍粑

TA贡献1815条经验 获得超6个赞

首先,ERROR_INVALID_PARAMETER错误是由最后一个参数引起的:cbSize,根据文档,它应该始终设置为 size 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 {

    devices := make([]rawInputDeviceList, size * devCount) // <- 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[0], &devCount, size)

    if err != nil {

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

    }

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

      fmt.Printf("Type: %v", devices[i].Type)

    }


  }

}


// 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

}


查看完整回答
反对 回复 2022-05-23
  • 1 回答
  • 0 关注
  • 225 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号