Dans un programme Julia qui s'exécute sous Linux, je dois lancer une action dédiée lorsqu'une fenêtre de console est redimensionnée. Alors comment, dans Julia, puis-je intercepter le signal système SIGWINCH (redimensionnement de la fenêtre) et y attacher une fonction qui effectue l'action requise?
En Ada, il est assez simple de le déclarer:
protected Signalhandler is
procedure Handlewindowresizing;
pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
end Signalhandler;
SOLUTION TENTATIVE BASÉE SUR L'IDÉE DE SCHEMER: J'essaie d'utiliser une bibliothèque C qui effectue la surveillance des interruptions 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);
}
Compilation et préparation de la bibliothèque
gcc -c -Wall -fPIC myLibrary.c
gcc -shared -fPIC -o myLibrary.so myLibrary.o
Programme en Julia qui utilise la C-Library:
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
Le programme Julia fonctionne correctement mais lorsque la fenêtre du terminal est redimensionnée, un défaut de segmentation (core dumped) est émis et le programme est dit quitté avec le code: 139.
La question est donc d'où vient ce défaut de segmentation? Du modèle de compilation? Julia n'a pas le droit de contrôler l'exécution du code dans la partie mémoire où C gère la surveillance du signal?
La suppression de l'opération println dans Sig_handler supprime l'erreur de segmentation:
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
Réponses:
Étant donné que personne n'a répondu à cette question jusqu'à présent, une solution de contournement possible pourrait être la surveillance asynchrone de la taille du terminal à certains intervalles de temps.
Et maintenant, exemple d'utilisation:
Tant que le terminal est vivant, toute modification de sa taille s'imprime
BOO!
.la source
Oui, c'est en effet une solution de repli qui n'est guère ce que l'on attend d'une nouvelle langue pleine de promesses ... mais faute de grives on peut effectivement manger des merles (sourire).
Mais si Julia n'a pas prévu de pouvoir prendre en compte les signaux système du monde Unix / Linux, il pourrait être possible de le faire en utilisant une bibliothèque C comme celle à laquelle accède signal.h.
Il faudrait définir une fonction julia faisant ce qui est attendu lors de la réception du signal système. Rendez-le utilisable en C comme Sig_handler et appelez de julia le signal d'instruction C (SIGWINCH, Sig_handler);
Je ne connais pas assez julia pour écrire le code exact. Mais c'est l'idée ...
la source
ccal
) et que vous souhaitez en faire plus tard un package Julia standard, je peux vous aider à l'empaqueter.