printf() and stdio in the Julia runtime
Libuv wrappers for stdio
julia.h
stdio.h
akışları için libuv sarmalayıcıları tanımlar:
uv_stream_t *JL_STDIN;
uv_stream_t *JL_STDOUT;
uv_stream_t *JL_STDERR;
... ve karşılık gelen çıktı fonksiyonları:
int jl_printf(uv_stream_t *s, const char *format, ...);
int jl_vprintf(uv_stream_t *s, const char *format, va_list args);
Bu printf
fonksiyonları, çıktı tamponlamasının birleştirilmiş bir şekilde yönetilmesini sağlamak için src/
ve cli/
dizinlerindeki .c
dosyaları tarafından gerektiği yerlerde kullanılır.
In special cases, like signal handlers, where the full libuv infrastructure is too heavy, jl_safe_printf()
can be used to write(2)
directly to STDERR_FILENO
:
void jl_safe_printf(const char *str, ...);
Interface between JL_STD* and Julia code
Base.stdin
, Base.stdout
ve Base.stderr
çalışma zamanında tanımlanan JL_STD*
libuv akışlarına bağlıdır.
Julia'nın __init__()
fonksiyonu (base/sysimg.jl
içinde) reinit_stdio()
( base/stream.jl
içinde) çağırarak Base.stdin
, Base.stdout
ve Base.stderr
için Julia nesneleri oluşturur.
reinit_stdio()
ccall
kullanarak JL_STD*
için işaretçileri alır ve her akışın türünü denetlemek için jl_uv_handle_type()
çağrısını yapar. Ardından, her akışı temsil etmek için bir Julia Base.IOStream
, Base.TTY
veya Base.PipeEndpoint
nesnesi oluşturur, örn.:
$ julia -e 'println(typeof((stdin, stdout, stderr)))'
Tuple{Base.TTY,Base.TTY,Base.TTY}
$ julia -e 'println(typeof((stdin, stdout, stderr)))' < /dev/null 2>/dev/null
Tuple{IOStream,Base.TTY,IOStream}
$ echo hello | julia -e 'println(typeof((stdin, stdout, stderr)))' | cat
Tuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY}
Base.read
ve Base.write
yöntemleri bu akışlar için ccall
kullanarak src/jl_uv.c
içindeki libuv sarmalayıcılarını çağırır, örneğin:
stream.jl: function write(s::IO, p::Ptr, nb::Integer)
-> ccall(:jl_uv_write, ...)
jl_uv.c: -> int jl_uv_write(uv_stream_t *stream, ...)
-> uv_write(uvw, stream, buf, ...)
printf() during initialization
jl_printf()
vb. gibi libuv
akışları, çalışma zamanının başlatılmasının ortalarına kadar mevcut değildir (bkz. init.c
, init_stdio()
). Bu noktadan önce yazdırılması gereken hata mesajları veya uyarılar, aşağıdaki mekanizma ile standart C kütüphanesi fwrite()
fonksiyonuna yönlendirilir:
sys.c
dosyasında, JL_STD*
akış işaretçileri tam sayı sabitlerine statik olarak başlatılmıştır: STD*_FILENO (0, 1 ve 2)
. jl_uv.c
dosyasında jl_uv_puts()
fonksiyonu uv_stream_t* stream
argümanını kontrol eder ve akış STDOUT_FILENO
veya STDERR_FILENO
olarak ayarlandığında fwrite()
çağrısını yapar.
Bu, belirli bir kod parçasının başlatma tamamlanmadan önce erişilebilir olup olmamasına bakılmaksızın, çalışma zamanı boyunca jl_printf()
'ın tutarlı bir şekilde kullanılmasına olanak tanır.
Legacy ios.c
library
src/support/ios.c
kütüphanesi femtolisp'den miras alınmıştır. Bu, çapraz platform tamponlu dosya G/Ç ve bellek içi geçici tamponlar sağlar.
ios.c
hala şu tarafından kullanılmaktadır:
src/flisp/*.c
src/dump.c
– serileştirme dosyası IO ve bellek tamponları için.src/staticdata.c
– serileştirme dosyası IO ve bellek tamponları için.base/iostream.jl
– dosya IO için (libuv eşdeğeri içinbase/fs.jl
'ye bakın).
ios.c
bu modüllerde çoğunlukla kendine özgü ve libuv I/O sisteminden ayrıdır. Ancak, femtolisp'in bir eski ios_t
akışı ile jl_printf()
'e çağrıda bulunduğu one place bulunmaktadır.
ios.h
dosyasında, ios_t.bm
alanının uv_stream_t.type
ile hizalanmasını sağlayan bir hack bulunmaktadır ve bu, ios_t.bm
için kullanılan değerlerin geçerli UV_HANDLE_TYPE
değerleriyle çakışmamasını garanti eder. Bu, uv_stream_t
işaretçilerinin ios_t
akışlarına işaret etmesine olanak tanır.
Bu, jl_printf()
çağrısı jl_static_show()
'a femtolisp'in fl_print()
fonksiyonu tarafından bir ios_t
akışı geçirildiği için gereklidir. Julia'nın jl_uv_puts()
fonksiyonu bunun için özel bir işleme sahiptir:
if (stream->type > UV_HANDLE_TYPE_MAX) {
return ios_write((ios_t*)stream, str, n);
}