winapi - 将复杂结构传递给 Windows API

标签 winapi raku kernel32 nativecall

我正在尝试使用 Perl 6 和(当然)NativeCall 从 Windows API 中使用 GetConsoleScreenBufferInfo(HANDLE, PCONSOLE_SCREEN_BUFFER_INFO) 函数。

我认为我已经正确设置了函数所需的 CONSOLE_SCREEN_BUFFER_INFO 结构,但是当我尝试转储其内容时,代码在调用后崩溃。

这是演示问题的最短(不完全但接近)的方法:

use NativeCall;

constant \HANDLE            := Pointer[void];
constant \SHORT             := int16;
constant \USHORT            := uint16;
constant \WORD              := uint16;
constant \DWORD             := uint32;
constant \BOOL              := int32;
constant \STD_OUTPUT_HANDLE := -11;
constant \STD_INPUT_HANDLE  := -10;

class COORD is repr('CStruct')            {
  has SHORT $.X;
  has SHORT $.Y;
}

class SMALL_RECT is repr("CStruct")            {
  has SHORT $.Left;
  has SHORT $.Top;
  has SHORT $.Right;
  has SHORT $.Bottom;
};

class CONSOLE_SCREEN_BUFFER_INFO is repr("CStruct")            {
  has COORD $.dwSize;
  has COORD $.dwCursorPosition;
  has WORD $.wAttributes;
  has SMALL_RECT $.srWindow;
  has COORD $.dwMaximumWindowSize;

  submethod TWEAK {
    $!dwSize := COORD.new;
    $!dwCursorPosition := COORD.new;
    $!srWindow := SMALL_RECT.new;
    $!dwMaximumWindowSize := COORD.new;
  }
}

# C: BOOL WINAPI GetConsoleScreenBufferInfo(_In_  HANDLE hConsoleOutput, _Out_ PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
sub GetConsoleScreenBufferInfo(HANDLE, CONSOLE_SCREEN_BUFFER_INFO is rw) is native("Kernel32.dll") returns BOOL { * };
sub GetStdHandle(DWORD) is native('Kernel32') returns Pointer[void]  { * };

my CONSOLE_SCREEN_BUFFER_INFO
  $info = CONSOLE_SCREEN_BUFFER_INFO.new;

my HANDLE
  $handle-o = GetStdHandle( STD_OUTPUT_HANDLE );

dd $info;
say "GetConsoleScreenBufferInfo ", GetConsoleScreenBufferInfo( $handle-o, $info );
say "Will I live?";
dd $info; #crashes without notice

非常欢迎任何有关崩溃原因以及如何修复它的提示。

最佳答案

对于作为结构的 CONSOLE_SCREEN_BUFFER_INFO 的成员,您需要使用 HAS 而不是 has,因为它们是嵌入的而不是由指针引用的(这是 Perl6 默认值)。

完成此操作后,您也可以删除TWEAK,以便读取代码

class CONSOLE_SCREEN_BUFFER_INFO is repr("CStruct") {
  HAS COORD $.dwSize;
  HAS COORD $.dwCursorPosition;
  has WORD $.wAttributes;
  HAS SMALL_RECT $.srWindow;
  HAS COORD $.dwMaximumWindowSize;
}

关于winapi - 将复杂结构传递给 Windows API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57599297/

相关文章:

c++ - RAS API。 sizeof(RASDIALPARAMS) 是错误的。错误 632

c++ - 以编程方式查找目录中的文件列表 C++ MFC

c++ - 如何判断线程是否启用了 WOW 文件系统重定向?

mysqld.exe - 找不到入口点

c - C 中的多线程问题

c++ - 我可以创建多少个 CRITICAL_SECTION?

grammar - 对 Raku 中无限的 <!before> 模式家族进行反匹配

signals - 如何在 Perl 6 中向进程 ID 发送信号?

raku - 如何将具有关联作用的类哈希对象传递给期望哈希的构造函数?

c# - SetFileTime 返回错误代码 5