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
Antworten:
Da diese Frage bisher noch niemand beantwortet hat, könnte eine mögliche Problemumgehung darin bestehen, die Größe des Terminals in bestimmten Zeitintervallen asynchron zu überwachen.
Und jetzt Beispielnutzung:
Solange das Terminal aktiv ist, wird jede Änderung seiner Größe gedruckt
BOO!
.quelle
Ja, es ist in der Tat eine Fallback-Lösung, die man von einer neuen Sprache voller Versprechen kaum erwartet ... aber mangels Drosseln können wir tatsächlich Amseln essen (Lächeln).
Aber wenn Julia nicht geplant hat, die Systemsignale der Unix / Linux-Welt berücksichtigen zu können, ist es möglicherweise möglich, dies mit einer C-Bibliothek wie der zu tun, auf die signal.h zugreift.
Wir müssten eine Julia-Funktion definieren, die das tut, was erwartet wird, wenn das Systemsignal empfangen wird. Machen Sie es in C als Sig_handler verwendbar und rufen Sie von Julia das C-Anweisungssignal (SIGWINCH, Sig_handler) auf;
Ich bin nicht genug mit Julia vertraut, um den genauen Code zu schreiben. Aber das ist die Idee ...
quelle
ccal
) und es später zu einem Standard-Julia-Paket machen möchten, kann ich Ihnen beim Packen helfen.