这个 Chez Scheme FFI 调用 user32.dll 的 SendInput 有什么问题?

huangapple go评论89阅读模式
英文:

What's wrong with this Chez Scheme FFI call to user32.dll SendInput?

问题

我之前从未在Chez Scheme的FFI中遇到过任何问题,它对你输入的内容非常宽容,但我似乎无法使这个函数不抛出错误。

目标是简单地模拟按下和释放左Windows键。

以下是你的代码的翻译部分:

  1. (load-shared-object "user32.dll")
  2. (define-ftype win32-input-ftype
  3. (struct (type unsigned-long)
  4. (mi (union (dx long)
  5. (dy long)
  6. (mouseData unsigned-long)
  7. (dwFlags unsigned-long)
  8. (time unsigned-long)
  9. (dwExtraInfo uptr)))
  10. (ki (union (wVk unsigned-short)
  11. (wScan unsigned-short)
  12. (dwFlags unsigned-long)
  13. (time unsigned-long)
  14. (dwExtraInfo uptr)))
  15. (hi (union (uMsg unsigned-long)
  16. (wParamL unsigned-short)
  17. (wParamH unsigned-short)))))
  18. ;; MSDN获取的结构信息
  19. ;; dwExtraInfo 实际上是一个 (* unsigned-long) ,但创建一个设置为0的虚拟ulong指针也没有效果。在其他ffi调用的工作代码中,一个可空的uptr也可以互换使用。
  20. (define-ftype input-array-ftype
  21. (array 2 win32-input-ftype)) ;; win32-input-ftype/INPUT[2]
  22. (define send-input-fp
  23. (foreign-procedure "SendInput"
  24. (unsigned-int
  25. (* input-array-ftype)
  26. int)
  27. unsigned-int))
  28. ;; MSDN定义SendInput的签名
  29. (define input-array
  30. (make-ftype-pointer input-array-ftype
  31. (foreign-alloc (ftype-sizeof input-array-ftype))))
  32. ;; 分配包含结构体的数组,并创建指向它的指针
  33. (ftype-set! input-array-ftype
  34. (0 type) input-array 1) ;; input_array[0].type = 1;
  35. (ftype-set! input-array-ftype
  36. (0 ki wVk) input-array #x5B) ;; input_array[0].ki.wVk = 0x5B;
  37. (ftype-set! input-array-ftype
  38. (0 ki wScan) input-array 0) ;; input_array[0].ki.wScan = 0;
  39. (ftype-set! input-array-ftype
  40. (0 ki dwFlags) input-array 0) ;; input_array[0].ki.dwFlags = 0;
  41. (ftype-set! input-array-ftype
  42. (0 ki time) input-array 0) ;; input_array[0].ki.time = 0;
  43. (ftype-set! input-array-ftype
  44. (0 ki dwExtraInfo) input-array 0) ;; input_array[0].dwExtraInfo = NULL;
  45. (ftype-set! input-array-ftype
  46. (1 type) input-array 1) ;; input_array[1].type = 1
  47. (ftype-set! input-array-ftype
  48. (1 ki wVk) input-array #x5B) ;; input_array[1].ki.wVk = 0x5B;
  49. (ftype-set! input-array-ftype
  50. (1 ki wScan) input-array 0) ;; input_array[1].ki.wScan = 0;
  51. (ftype-set! input-array-ftype
  52. (1 ki dwFlags) input-array 2) ;; input_array[1].ki.dwFlags = 2;
  53. (ftype-set! input-array-ftype
  54. (1 ki time) input-array 0) ;; input_array[1].ki.time = 0;
  55. (ftype-set! input-array-ftype
  56. (1 ki dwExtraInfo) input-array 0) ;; input_array[1].ki.dwExtraInfo = NULL;
  57. (display (send-input-fp 2 input-array
  58. (ftype-sizeof win32-input-ftype)))
  59. ;; 所有事件都返回0,表示失败,并且GetLastError87,表示无效的参数。
  60. ;; 递归遍历结构表明它们都按预期分配,而ftype-sizeof也在预期范围内。

以下是你要模仿的工作中的C++代码的翻译部分:

  1. (define (press-windows-key)
  2. (let ((inputs (make-c-struct-array 'input 2)))
  3. (c-struct-set! inputs 0 'type 1)
  4. (c-struct-set! inputs 0 'ki.wVk #x5B)
  5. (c-struct-set! inputs 0 'ki.wScan 0)
  6. (c-struct-set! inputs 0 'ki.time 0)
  7. (c-struct-set! inputs 0 'ki.dwFlags 0)
  8. (c-struct-set! inputs 0 'ki.dwExtraInfo 0)
  9. (c-struct-set! inputs 1 'type 1)
  10. (c-struct-set! inputs 1 'ki.wVk #x5B)
  11. (c-struct-set! inputs 1 'ki.wScan 0)
  12. (c-struct-set! inputs 1 'ki.time 0)
  13. (c-struct-set! inputs 1 'ki.dwFlags 2)
  14. (c-struct-set! inputs 1 'ki.dwExtraInfo 0)
  15. (let ((uSent (send-input-fp 2 inputs (c-struct-sizeof 'input))))
  16. (display uSent)))))

希望这有助于你解决问题!如果有其他问题,请随时提问。

英文:

I've never had any trouble with Chez Scheme FFI before, it's extremely forgiving with whatever you throw at it, but I can't seem to get this function not to throw errors.

The goal is to simply virtually press and release the left windows key.

  1. (load-shared-object "user32.dll")
  2. (define-ftype win32-input-ftype
  3. (struct (type unsigned-long)
  4. (mi (union (dx long)
  5. (dy long)
  6. (mouseData unsigned-long)
  7. (dwFlags unsigned-long)
  8. (time unsigned-long)
  9. (dwExtraInfo uptr)))
  10. (ki (union (wVk unsigned-short)
  11. (wScan unsigned-short)
  12. (dwFlags unsigned-long)
  13. (time unsigned-long)
  14. (dwExtraInfo uptr)))
  15. (hi (union (uMsg unsigned-long)
  16. (wParamL unsigned-short)
  17. (wParamH unsigned-short)))))
  18. ;; Struct info from MSDN
  19. ;; dwExtraInfo is actually an (* unsigned-long), but creating a dummy ulong pointer set to 0
  20. ;; also had no effect. A nullable uptr is also interchangeable in working code for other ffi calls
  21. (define-ftype input-array-ftype
  22. (array 2 win32-input-ftype)) ;; win32-input-ftype/INPUT[2]
  23. (define send-input-fp
  24. (foreign-procedure "SendInput"
  25. (unsigned-int
  26. (* input-array-ftype)
  27. int)
  28. unsigned-int))
  29. ;; Define signature for SendInput from MSDN
  30. (define input-array
  31. (make-ftype-pointer input-array-ftype
  32. (foreign-alloc (ftype-sizeof input-array-ftype))))
  33. ;; Allocate the array with the structs and create a pointer to it
  34. (ftype-set! input-array-ftype
  35. (0 type) input-array 1) ;; input_array[0].type = 1;
  36. (ftype-set! input-array-ftype
  37. (0 ki wVk) input-array #x5B) ;; input_array[0].ki.wVk = 0x5B;
  38. (ftype-set! input-array-ftype
  39. (0 ki wScan) input-array 0) ;; input_array[0].ki.wScan = 0;
  40. (ftype-set! input-array-ftype
  41. (0 ki dwFlags) input-array 0) ;; input_array[0].ki.dwFlags = 0;
  42. (ftype-set! input-array-ftype
  43. (0 ki time) input-array 0) ;; input_array[0].ki.time = 0;
  44. (ftype-set! input-array-ftype
  45. (0 ki dwExtraInfo) input-array 0) ;; input-array[0].dwExtraInfo = NULL;
  46. (ftype-set! input-array-ftype
  47. (1 type) input-array 1) ;; input_array[1].type = 1
  48. (ftype-set! input-array-ftype
  49. (1 ki wVk) input-array #x5B) ;; input_array[1].ki.wVk = 0x5B;
  50. (ftype-set! input-array-ftype
  51. (1 ki wScan) input-array 0) ;; input_array[1].ki.wScan = 0;
  52. (ftype-set! input-array-ftype
  53. (1 ki dwFlags) input-array 2) ;; input_array[1].ki.dwFlags = 2;
  54. (ftype-set! input-array-ftype
  55. (1 ki time) input-array 0) ;; input_array[1].ki.time = 0;
  56. (ftype-set! input-array-ftype
  57. (1 ki dwExtraInfo) input-array 0) ;; input_array[1].ki.dwExtraInfo = NULL;
  58. (display (send-input-fp 2 input-array
  59. (ftype-sizeof win32-input-ftype)))
  60. ;; The return is 0 for all events failing and GetLastError is 87 invalid parameters.
  61. ;; Recursing through the structs show they're all allocated as expected and the ftype-sizeof
  62. ;; is in the expected area as well.

And here's the working C++ code that I'm trying to mimic:

  1. void PressWindowsKey()
  2. {
  3. INPUT inputs[2] = {};
  4. INPUT *input_ptr = inputs;
  5. inputs[0].type = 1;
  6. inputs[0].ki.wVk = 0x5B;
  7. inputs[0].ki.wScan = 0;
  8. inputs[0].ki.time = 0;
  9. inputs[0].ki.dwFlags = 0;
  10. inputs[0].ki.dwExtraInfo = NULL;
  11. inputs[1].type = 1;
  12. inputs[1].ki.wVk = 0x5B;
  13. inputs[1].ki.wScan = 0;
  14. inputs[1].ki.time = 0;
  15. inputs[1].ki.dwFlags = 2;
  16. inputs[1].ki.dwExtraInfo = NULL;
  17. UINT uSent = SendInput(2, input_ptr, sizeof(INPUT));
  18. }

Any help would be appreciated!
This is on stand-alone 32-bit/64-bit Chez Scheme 9.5.4 (I've tried both), but I'm attaching Racket to the tags since if I'm not mistaken the Chez hosted within has the same FFI.

答案1

得分: 1

以下是您要翻译的内容:

"The code almost works as is, but as mentioned in the Chez Scheme documentation, allocating arrays is conservative in the number of bytes is uses. SendInput is also very particular about arg 3 being the exact number of bytes.

By manually typing in 28 bytes for arg 3 of SendInput instead of using (ftype-sizeof), the program works.

Edit:
I got some strange behavior from the (unions as well. Switching the foreign type definition to:

  1. (define-ftype win32-input-ftype
  2. (struct (type unsigned-long)
  3. (ki (struct (wVk unsigned-short)
  4. (wScan unsigned-short)
  5. (dwFlags unsigned-long)
  6. (time unsigned-long)
  7. (dwExtraInfo uptr)))))

fixed this problem. Good luck"

英文:

The code almost works as is, but as mentioned in the Chez Scheme documentation, allocating arrays is conservative in the number of bytes is uses. SendInput is also very particular about arg 3 being the exact number of bytes.

By manually typing in 28 bytes for arg 3 of SendInput instead of using (ftype-sizeof), the program works.

Edit:
I got some strange behavior from the (unions as well. Switching the foreign type definition to:

  1. (define-ftype win32-input-ftype
  2. (struct (type unsigned-long)
  3. (ki (struct (wVk unsigned-short)
  4. (wScan unsigned-short)
  5. (dwFlags unsigned-long)
  6. (time unsigned-long)
  7. (dwExtraInfo uptr)))))

fixed this problem. Good luck

huangapple
  • 本文由 发表于 2023年7月11日 07:38:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76657918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定