将复杂结构传递给 Windows API
Pass a complex struct to the Windows API
我正在尝试使用 Windows API 中的 GetConsoleScreenBufferInfo(HANDLE, PCONSOLE_SCREEN_BUFFER_INFO)
函数,使用 Perl 6 和(当然)NativeCall。
我想我已经正确设置了函数所需的 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;
}
我正在尝试使用 Windows API 中的 GetConsoleScreenBufferInfo(HANDLE, PCONSOLE_SCREEN_BUFFER_INFO)
函数,使用 Perl 6 和(当然)NativeCall。
我想我已经正确设置了函数所需的 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;
}