W programie Julia, który działa pod Linuksem, muszę uruchomić dedykowane działanie, gdy zmieni się rozmiar okna konsoli. Jak więc w Julii mogę przechwycić sygnał systemowy SIGWINCH (zmiana rozmiaru okna) i dołączyć do niego funkcję, która wykonuje wymagane działanie?
W Adzie deklaracja jest dość prosta:
protected Signalhandler is
procedure Handlewindowresizing;
pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
end Signalhandler;
ROZWIĄZANIE TENTATYWNE W OPARCIU O POMYSŁ SCHEMERA: Próbuję użyć biblioteki C, która prowadzi monitorowanie przerw SIGWINCH.
myLibrary.h
void Winresize (void Sig_Handler());
myLibrary.c
#include "myLibrary.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
void Winresize(void sig_handler (void)) {
signal(SIGWINCH, sig_handler);
}
Kompilacja i przygotowanie biblioteki
gcc -c -Wall -fPIC myLibrary.c
gcc -shared -fPIC -o myLibrary.so myLibrary.o
Program w Julii korzystający z biblioteki C:
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
Program Julia działa poprawnie, ale po zmianie rozmiaru okna terminala generowany jest błąd segmentacji (zrzut pamięci) i program kończy się kodem: 139.
Pytanie brzmi, skąd bierze się ta usterka segmentacji? Z modelu kompilacji? Julia nie ma prawa kontrolować wykonywania kodu w części pamięci, w której C zarządza monitorowaniem sygnału?
Usunięcie operacji println w module Sig_handler tłumi błąd segmentacji:
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
Odpowiedzi:
Ponieważ do tej pory nikt nie odpowiedział na to pytanie, jednym z możliwych obejść może być asynchroniczne monitorowanie wielkości terminala w określonych odstępach czasu.
A teraz przykładowe użycie:
Tak długo, jak terminal będzie żył, będą drukowane wszelkie zmiany jego rozmiaru
BOO!
.źródło
Tak, to rzeczywiście rozwiązanie awaryjne, które nie jest tym, czego można oczekiwać od nowego języka pełnego obietnic ... ale z powodu braku pleśniawki możemy faktycznie jeść kosy (uśmiech).
Ale jeśli Julia nie planuje brać pod uwagę sygnałów systemowych ze świata Unix / Linux, może to być możliwe przy użyciu biblioteki C, takiej jak ta, do której uzyskuje dostęp.
Musielibyśmy zdefiniować funkcję Julii wykonującą to, czego się oczekuje po odebraniu sygnału systemowego. Uczyń go użytecznym w C jako Sig_handler i wywołaj z Julii sygnał instrukcji C (SIGWINCH, Sig_handler);
Nie jestem wystarczająco zaznajomiony z Julią, aby napisać dokładny kod. Ale to jest pomysł ...
źródło
ccal
) i chcesz później przekształcić go w standardowy pakiet Julii, mogę pomóc w jego pakowaniu.