我最近看到了四年前Manfred Mahlow的一篇文章,这篇文章几乎解决了我遇到的一个问题。文章"使用Glade在Forth中创建GTK+应用程序"谈到了信号处理程序,指出不能使用Forth,只能使用C来创建它们。我认为我的问题仍然很小,但我被难住了,我将非常感谢任何建议。其次,如果有人知道如何在地址中不使用破折号的情况下向马洛先生发送电子邮件,我很乐意听到
我正在使用Linux版本的SwiftForth编写一个应用程序,以创建一个自定义窗口,接收按键并写入该窗口。我的目标是实现Charles Moore的colorForth,增强和更用户友好。我决定使用GTK+,对此知之甚少,但除了回调(信号处理程序)之外,我一直很成功。整件事只有两页代码,所以我把它放在这里:
------------------------ COLOR FORTH -----------------------
ANEW TASK-COLORFORTH
LIBRARY /usr/lib/i386-linux-gnu/libgtk-3.so.0.1000.8
FUNCTION: gtk_window_new ( code -- addr )
FUNCTION: gtk_widget_destroy ( wptr -- )
FUNCTION: gtk_window_close ( wptr -- )
FUNCTION: gtk_widget_show ( wptr -- )
FUNCTION: gtk_init ( -- )
FUNCTION: gtk_window_set_decorated ( wptr flag -- )
FUNCTION: gtk_window_move ( wptr x y -- )
FUNCTION: gtk_widget_new ( n addr -- ) ( try 0 0 )
FUNCTION: gtk_widget_map ( wptr -- )
FUNCTION: gtk_widget_show_all ( wptr -- )
FUNCTION: gtk_window_get_screen ( wptr -- wgptr )
FUNCTION: gtk_window_present ( wptr -- )
FUNCTION: gtk_window_set_title ( wptr TitlePtr -- )
FUNCTION: gtk_window_resize ( wptr width height -- )
FUNCTION: gtk_widget_modify_bg ( wptr state cptr -- )
FUNCTION: gtk_widget_modify_fg ( wptr state cptr -- )
FUNCTION: gtk_widget_modify_text ( wptr state cptr -- )
FUNCTION: gtk_widget_modify_base ( wptr statre cptr -- )
FUNCTION: g_signal_connect_data ( wptr name callback data 0 0 -- )
FUNCTION: gtk_main ( -- )
FUNCTION: gtk_main_quit ( -- )
FUNCTION: gtk_widget_set_events ( wptr flag -- )
LIBRARY /usr/lib/i386-linux-gnu/libgdk-3.so.0.1000.8
FUNCTION: gdk_event_get_keyval ( eptr kptr -- )
FUNCTION: gdk_event_get_state ( eptr sptr -- )
FUNCTION: gdk_event_get_event_type ( eptr -- type ) ( requires GET.RETURN )
LIBRARY /usr/lib/i386-linux-gnu/libgio-2.0.so.0.4000.0
LIBRARY /lib/i386-linux-gnu/libglib-2.0.so.0.4000.0
LIBRARY /usr/lib/i386-linux-gnu/libpango-1.0.so.0.3600.3
LIBRARY /usr/lib/i386-linux-gnu/libatk-1.0.so.0.21009.1
LIBRARY /usr/lib/i386-linux-gnu/libgobject-2.0.so.0.4000.0
LIBRARY /usr/lib/i386-linux-gnu/libgdk_pixbuf-2.0.so.0.3000.7
VARIABLE Window-Ptr
VARIABLE Event-Ptr
VARIABLE KeyVal
VARIABLE KeyState
Z" ColorForth" VALUE Title
Z" key_press_event" VALUE Keypress-Name
Z" delete_event" VALUE Delete-Event-Name
Z" destroy" VALUE Destroy-Name
CREATE Background 0 , 0 H, 0 H, $2000 H,
CREATE Black 0 , 0 H, 0 H, 0 H,
CREATE White 0 , $E000 H, $E000 H, $8000 H,
----------------------------------------------------------------
ICODE LEAVE.FALSE
EAX EAX SUB
RET
END-CODE
ICODE GET.RETURN
4 # EBP SUB
EBX 0 [EBP] MOV
EAX EBX MOV
RET
END-CODE
This may be the part where I am having problems
: SHUTDOWN
Window-Ptr @ DUP gtk_window_close
gtk_widget_destroy
;
: CB.DELETE.EVENT ( wptr data -- false to destroy )
RDROP RDROP ( assuming 2 paramaters on Rstack and return -1 )
LEAVE.FALSE
;
: CB.DESTROY ( wptr data -- )
RDROP RDROP ( two parameters here )
gtk_main_quit
;
: CB.KEYPRESS ( wptr eptr data -- ) ( assuming 3 parameters on Rstack )
Window-Ptr @ . R> . R> . R> . R@ ( This for diagnosis – eventually )
SHUTDOWN ( goes to a [SWITCH )
;
: STARTUP ( -- )
Window-Ptr OFF Event-Ptr OFF
gtk_init
0 gtk_window_new ?DUP ( 0 = GTK_WINDOW_TOPLEVEL )
IF DUP Window-Ptr !
DUP 1024 gtk_widget_set_events ( 1024 for Keypress signals )
DUP Title gtk_window_set_title
DUP 1280 850 gtk_window_resize
DUP 0 gtk_window_set_decorated
DUP 0 Background gtk_widget_modify_bg
DUP Delete-Event-Name [ ' CB.DELETE.EVENT +ORIGIN ] LITERAL 0
0 0 g_signal_connect_data
DUP Destroy-Name [ ' CB.DESTROY +ORIGIN ] LITERAL 0
0 0 g_signal_connect_data
DUP Keypress-Name [ ' CB.KEYPRESS +ORIGIN ] LITERAL 0
0 0 g_signal_connect_data
gtk_widget_show
THEN
gtk_main
;
我无法使用通常的g_signal_connect,因为我在任何库中都找不到它。如果它出现了,我会使用它,因为代码更简单。然而,上面的代码是编译的,当我键入STARTUP时,它就是这样做的。正如我所指定的,窗口在那里,信号已经设置,但按下任何键都会导致SwiftForth出现"分段故障"。
正如您所看到的,我正在将处理程序的绝对地址提供给信号连接函数。我还尝试将该地址放入变量中,并将其作为指针进行处理,但这会产生GTK+错误。
在编写处理程序时,我假设它将像任何库调用一样运行。输入参数将在返回堆栈上,由GTK在处理程序代码执行时提供,我应该将任何返回放入EAX中。但这种分析可能是错误的。我可能准备的地址错误,或者处理程序的参数错误,或者有完全错误的概念
我希望,尽管有人说处理程序必须在C中,但如果必要的话,可以用汇编程序来模拟C代码的功能。
我感觉到我离取得这一突破还有一个障碍,如果有人能给我一些建议或地方,我将不胜感激。
FUNCTION: g_signal_connect_data ( wptr name callback data 0 0 -- )
我看到你正在使用' CB.DELETE.EVENT +ORIGIN
之类的东西作为回调参数。
你不应该使用Forth回调开始吗?你的CB.DELETE.EVENT
(和其他人)需要并期望上下文
在SwiftForth,这可以通过实现
' CB.DELETE.EVENT 2 CB: *CB.DELETE>EVENT
将*CB.DELETE>EVENT
作为回调参数传递给g_signal_connect_data
CCD_ 6在CCD_要运行的临时Forth环境。请参阅SwiftForth手册用于访问给定给回调的参数。当然其他回调也应该进行类似的调整。
注:SwiftForth以特定的方式处理输入。另外第四个系统在处理回调输入的方式上有所不同参数。但总的来说,不要盲目依赖返回堆栈。请务必查看Forth文档。
而导入库中的单词有助于非Forth函数在Forth环境中运行,相反,在中运行Forth单词一个外来上下文,是用回调词完成的。他们允许对于信号处理程序、完成处理程序、异常处理程序,POSIX线程的启动例程,Objective-C的方法实现类等。许多Forth系统在类似的操作系统下运行SwiftForth、VFX、iForth、MacForth、iMops和Gforth提供了方法创建Forth回调。所以任何索赔Forth都不能在这里使用我想是被驳斥了。请参阅此Forth+GTK示例。
顺便说一句,我在SwiftForth OS X中运行了改编后的代码。好的;-)