从 C 绑定传递的 Ada SDL Unchecked Union
Ada SDL Unchecked Union passed from C binding
我正在使用 AdaSDL2,这是一个绑定到 C 库的第三方。 SDL 中的事件是通过联合处理的,如参考文献所示:
http://www.willusher.io/sdl2%20tutorials/2013/08/20/lesson-4-handling-events/
问题在于绑定将 SDL_Event 类型定义为未检查联合,因此您无法检查判别式以查看它是什么类型。这是类型的定义:
type SDL_Event (discr : C.unsigned := 0) is record
case discr is
when 0 =>
typ : aliased Uint32;
when 1 =>
common : aliased SDL_CommonEventRecord;
when 2 =>
window : aliased SDL_WindowEventRecord;
when 3 =>
key : aliased SDL_KeyboardEventRecord;
when 4 =>
edit : aliased SDL_TextEditingEventRecord;
when 5 =>
text : aliased SDL_TextInputEventRecord;
when 6 =>
motion : aliased SDL_MouseMotionEventRecord;
when 7 =>
button : aliased SDL_MouseButtonEventRecord;
when 8 =>
wheel : aliased SDL_MouseWheelEventRecord;
when 9 =>
jaxis : aliased SDL_JoyAxisEventRecord;
when 10 =>
jball : aliased SDL_JoyBallEventRecord;
when 11 =>
jhat : aliased SDL_JoyHatEventRecord;
when 12 =>
jbutton : aliased SDL_JoyButtonEventRecord;
when 13 =>
jdevice : aliased SDL_JoyDeviceEventRecord;
when 14 =>
caxis : aliased SDL_ControllerAxisEventRecord;
when 15 =>
cbutton : aliased SDL_ControllerButtonEventRecord;
when 16 =>
cdevice : aliased SDL_ControllerDeviceEventRecord;
when 17 =>
quit : aliased SDL_QuitEventRecord;
when 18 =>
user : aliased SDL_UserEventRecord;
when 19 =>
syswm : aliased SDL_SysWMEventRecord;
when 20 =>
tfinger : aliased SDL_TouchFingerEventRecord;
when 21 =>
mgesture : aliased SDL_MultiGestureEventRecord;
when 22 =>
dgesture : aliased SDL_DollarGestureEventRecord;
when 23 =>
drop : aliased SDL_DropEventRecord;
when others =>
padding : aliased SDL_Event_padding_array;
end case;
end record;
pragma Convention (C_Pass_By_Copy, SDL_Event);
pragma Unchecked_Union (SDL_Event);
所以当上面参考中的示例代码说要检查 e.type 时,我在 Ada 类型中没有相关值。当我尝试这个时:
procedure Process_Events is
E : access SDL_Event;
begin
while SDL_PollEvent(E) = 1 loop
if E.discr = SDL_SHUTDOWN then
Ada.Text_IO.Put("Shutdown requested.");
Ada.Task_Identification.Abort_Task(Ada.Task_Identification.Current_Task);
end if;
end loop;
end Process_Events;
GNAT 说“无法引用 Unchecked_Union 的判别式。我尝试了几个不同的想法来弄清楚它是什么类型的事件,但到目前为止 none 似乎既可行又有效。对此有通用的解决方案吗,或者有人有任何想法吗?谢谢。
在我看来,所有在区分组件中使用的记录类型都以(例如)
开头
type SDL_CommonEventRecord is record
typ : aliased Uint32;
timestamp : aliased Uint32;
end record;
并且这些将被覆盖,所以 typ
是 SDL_Event
的前 4 个字节;也就是说,typ
、common.typ
、window.typ
都引用存储中的相同数据。
我猜你应该写一个 case 语句来处理这个:
case E.typ is
when SDL_WINDOWEVENT =>
-- use E.window components
when SDL_KEYDOWN =>
-- use E.key components for key-down
when SDL_KEYUP =>
-- use E.key components for key-up
...
end case;
我正在使用 AdaSDL2,这是一个绑定到 C 库的第三方。 SDL 中的事件是通过联合处理的,如参考文献所示:
http://www.willusher.io/sdl2%20tutorials/2013/08/20/lesson-4-handling-events/
问题在于绑定将 SDL_Event 类型定义为未检查联合,因此您无法检查判别式以查看它是什么类型。这是类型的定义:
type SDL_Event (discr : C.unsigned := 0) is record
case discr is
when 0 =>
typ : aliased Uint32;
when 1 =>
common : aliased SDL_CommonEventRecord;
when 2 =>
window : aliased SDL_WindowEventRecord;
when 3 =>
key : aliased SDL_KeyboardEventRecord;
when 4 =>
edit : aliased SDL_TextEditingEventRecord;
when 5 =>
text : aliased SDL_TextInputEventRecord;
when 6 =>
motion : aliased SDL_MouseMotionEventRecord;
when 7 =>
button : aliased SDL_MouseButtonEventRecord;
when 8 =>
wheel : aliased SDL_MouseWheelEventRecord;
when 9 =>
jaxis : aliased SDL_JoyAxisEventRecord;
when 10 =>
jball : aliased SDL_JoyBallEventRecord;
when 11 =>
jhat : aliased SDL_JoyHatEventRecord;
when 12 =>
jbutton : aliased SDL_JoyButtonEventRecord;
when 13 =>
jdevice : aliased SDL_JoyDeviceEventRecord;
when 14 =>
caxis : aliased SDL_ControllerAxisEventRecord;
when 15 =>
cbutton : aliased SDL_ControllerButtonEventRecord;
when 16 =>
cdevice : aliased SDL_ControllerDeviceEventRecord;
when 17 =>
quit : aliased SDL_QuitEventRecord;
when 18 =>
user : aliased SDL_UserEventRecord;
when 19 =>
syswm : aliased SDL_SysWMEventRecord;
when 20 =>
tfinger : aliased SDL_TouchFingerEventRecord;
when 21 =>
mgesture : aliased SDL_MultiGestureEventRecord;
when 22 =>
dgesture : aliased SDL_DollarGestureEventRecord;
when 23 =>
drop : aliased SDL_DropEventRecord;
when others =>
padding : aliased SDL_Event_padding_array;
end case;
end record;
pragma Convention (C_Pass_By_Copy, SDL_Event);
pragma Unchecked_Union (SDL_Event);
所以当上面参考中的示例代码说要检查 e.type 时,我在 Ada 类型中没有相关值。当我尝试这个时:
procedure Process_Events is
E : access SDL_Event;
begin
while SDL_PollEvent(E) = 1 loop
if E.discr = SDL_SHUTDOWN then
Ada.Text_IO.Put("Shutdown requested.");
Ada.Task_Identification.Abort_Task(Ada.Task_Identification.Current_Task);
end if;
end loop;
end Process_Events;
GNAT 说“无法引用 Unchecked_Union 的判别式。我尝试了几个不同的想法来弄清楚它是什么类型的事件,但到目前为止 none 似乎既可行又有效。对此有通用的解决方案吗,或者有人有任何想法吗?谢谢。
在我看来,所有在区分组件中使用的记录类型都以(例如)
开头type SDL_CommonEventRecord is record
typ : aliased Uint32;
timestamp : aliased Uint32;
end record;
并且这些将被覆盖,所以 typ
是 SDL_Event
的前 4 个字节;也就是说,typ
、common.typ
、window.typ
都引用存储中的相同数据。
我猜你应该写一个 case 语句来处理这个:
case E.typ is
when SDL_WINDOWEVENT =>
-- use E.window components
when SDL_KEYDOWN =>
-- use E.key components for key-down
when SDL_KEYUP =>
-- use E.key components for key-up
...
end case;