在 Linux 下运行的 Julia 程序中,我需要在调整控制台窗口大小时启动一个专用操作。那么在 Julia 中,我如何拦截系统信号 SIGWINCH(窗口大小调整)并将其附加到一个执行所需操作的函数上?
在 Ada 中,声明它相当简单:
protected Signalhandler is
procedure Handlewindowresizing;
pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
end Signalhandler;
Run Code Online (Sandbox Code Playgroud)
基于 SCHEMER 思想的暂定解决方案:我尝试使用 C 库进行 SIGWINCH 中断监视。
我的图书馆.h
void Winresize (void Sig_Handler());
Run Code Online (Sandbox Code Playgroud)
我的图书馆
#include "myLibrary.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void Winresize(void sig_handler (void)) {
signal(SIGWINCH, sig_handler);
}
Run Code Online (Sandbox Code Playgroud)
编译和库准备
gcc -c -Wall -fPIC myLibrary.c
gcc -shared -fPIC -o myLibrary.so myLibrary.o
使用 C-Library 的 Julia 程序:
function getc1()
ret = ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), stdin.handle, true)
ret == 0 || error("unable to switch to raw mode")
c = read(stdin, UInt8)
ccall(:jl_tty_set_mode, Int32, (Ptr{Cvoid},Int32), stdin.handle, false)
c
end
function traitement() println(displaysize(stdout)); end
Mon_traitement_c = @cfunction(traitement, Cvoid, ())
ccall((:Winresize, "/home/Emile/programmation/Julia/myLibrary.so"), Cvoid, (Ptr{Cvoid},), Mon_traitement_c)
while true
println(getc1())
end
Run Code Online (Sandbox Code Playgroud)
Julia 程序运行正常,但是当调整终端窗口的大小时,会发出分段错误(核心转储)并且程序被说退出,代码为:139。
所以问题是这个分段错误从何而来?从编译模型?Julia 无权在 C 管理信号监控的内存部分控制代码执行?
删除 Sig_handler 中的 println 操作抑制分段错误:
curr_size = displaysize(stdout)
new_size = curr_size
function traitement() global new_size ; new_size = displaysize(stdout); return end
Mon_traitement_c = @cfunction(traitement, Cvoid, ())
ccall((:Winresize, "/home/Emile/programmation/Julia/myLibrary.so"), Cvoid, (Ptr{Cvoid},), Mon_traitement_c)
while true
global curr_size, new_size
if new_size != curr_size
curr_size = new_size
println(curr_size)
end
sleep(0.1)
end
Run Code Online (Sandbox Code Playgroud)
由于到目前为止还没有人回答这个问题,一种可能的解决方法是在某些时间间隔内异步监视终端的大小。
function monitor_term(func)
@async begin
curr_size = displaysize(stdout)
while (true)
sleep(0.1)
new_size = displaysize(stdout)
if new_size != curr_size
curr_size = new_size
func()
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
现在示例用法:
julia> monitor_term(() -> print("BOO!"))
Task (runnable) @0x0000000013071710
Run Code Online (Sandbox Code Playgroud)
只要终端处于活动状态,对其大小的任何更改都会打印BOO!。
| 归档时间: |
|
| 查看次数: |
289 次 |
| 最近记录: |