In einem Julia-Programm, das unter Linux ausgeführt wird, muss ich eine dedizierte Aktion starten, wenn die Größe eines Konsolenfensters geändert wird. Wie kann ich in Julia das Systemsignal SIGWINCH (Fenstergrößenänderung) abfangen und eine Funktion anhängen, die die erforderliche Aktion ausführt?
In Ada ist es ziemlich einfach, es zu erklären:
protected Signalhandler is
procedure Handlewindowresizing;
pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
end Signalhandler;
VORLÄUFIGE LÖSUNG AUF DER GRUNDLAGE DER SCHEMER-IDEE: Ich versuche, eine C-Bibliothek zu verwenden, die die SIGWINCH-Unterbrechungsüberwachung durchführt.
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);
}
Zusammenstellung & Bibliotheksvorbereitung
gcc -c -Wall -fPIC myLibrary.c
gcc -shared -fPIC -o myLibrary.so myLibrary.o
Programm in Julia, das die C-Bibliothek nutzt:
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
Das Julia-Programm wird ordnungsgemäß ausgeführt, aber wenn die Größe des Terminalfensters geändert wird, wird ein Segmentierungsfehler (Core Dumped) ausgegeben und das Programm mit dem Code 139 beendet.
Die Frage ist also, woher dieser Segmentierungsfehler kommt. Aus dem Kompilierungsmodell? Julia hat nicht das Recht, die Codeausführung in dem Speicherbereich zu steuern, in dem C die Signalüberwachung verwaltet.
Durch Entfernen der Druckoperation in Sig_handler wird der Segmentierungsfehler unterdrückt:
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