En un programa de Julia que se ejecuta en Linux, necesito iniciar una acción dedicada cuando se cambia el tamaño de una ventana de consola. Entonces, ¿cómo en Julia, puedo interceptar la señal del sistema SIGWINCH (cambio de tamaño de ventana) y asignarle una función que realice la acción requerida?
En Ada es bastante sencillo declararlo:
protected Signalhandler is
procedure Handlewindowresizing;
pragma Attach_Handler (Handlewindowresizing, SIGWINCH);
end Signalhandler;
SOLUCIÓN TENTATIVA BASADA EN LA IDEA DEL ESQUEMERO: Intento usar una Biblioteca C que realiza el monitoreo de interrupción 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);
}
Recopilación y preparación de la biblioteca.
gcc -c -Wall -fPIC myLibrary.c
gcc -shared -fPIC -o myLibrary.so myLibrary.o
Programa en Julia que usa la Biblioteca 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
El programa Julia se ejecuta correctamente, pero cuando se cambia el tamaño de la ventana del terminal, se emite un fallo de segmentación (núcleo volcado) y se dice que el programa salió con el código: 139.
Entonces, la pregunta es ¿de dónde viene esta falla de segmentación? ¿Del modelo de compilación? ¿Julia no tiene derecho a controlar la ejecución del código en la parte de memoria donde C gestiona la supervisión de la señal?
Eliminar la operación println en Sig_handler suprime el error de segmentación:
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
Respuestas:
Como nadie ha respondido esta pregunta hasta ahora, una posible solución podría ser monitorear asincrónicamente el tamaño del terminal en algunos intervalos de tiempo.
Y ahora muestra el uso:
Mientras el terminal esté vivo, se imprimirá cualquier cambio en su tamaño
BOO!
.fuente
Sí, de hecho es una solución alternativa que difícilmente es lo que uno espera de un nuevo lenguaje lleno de promesas ... pero por falta de zorzales podemos comer mirlos (sonrisa).
Pero si Julia no ha planeado tener en cuenta las señales del sistema del mundo Unix / Linux, podría ser posible hacerlo usando una biblioteca C como la que accede a signal.h.
Tendríamos que definir una función julia haciendo lo que se espera cuando se recibe la señal del sistema. Hazlo utilizable en C como Sig_handler y llama desde julia la señal de la declaración C (SIGWINCH, Sig_handler);
No estoy lo suficientemente familiarizado con Julia para escribir el código exacto. Pero esta es la idea ...
fuente
ccal
) y luego quiere convertirlo en un paquete estándar de Julia, puedo ayudarlo a empaquetarlo.