Movatterモバイル変換


[0]ホーム

URL:


GitHub

printf() and stdio in the Julia runtime

Libuv wrappers for stdio

julia.h defineslibuv wrappers for thestdio.h streams:

uv_stream_t *JL_STDIN;uv_stream_t *JL_STDOUT;uv_stream_t *JL_STDERR;

... and corresponding output functions:

int jl_printf(uv_stream_t *s, const char *format, ...);int jl_vprintf(uv_stream_t *s, const char *format, va_list args);

Theseprintf functions are used by the.c files in thesrc/ andcli/ directories wherever stdio is needed to ensure that output buffering is handled in a unified way.

In special cases, like signal handlers, where the full libuv infrastructure is too heavy,jl_safe_printf() can be used towrite(2) directly toSTDERR_FILENO:

void jl_safe_printf(const char *str, ...);

Interface between JL_STD* and Julia code

Base.stdin,Base.stdout andBase.stderr are bound to theJL_STD* libuv streams defined in the runtime.

Julia's__init__() function (inbase/sysimg.jl) callsreinit_stdio() (inbase/stream.jl) to create Julia objects forBase.stdin,Base.stdout andBase.stderr.

reinit_stdio() usesccall to retrieve pointers toJL_STD* and callsjl_uv_handle_type() to inspect the type of each stream. It then creates a JuliaBase.IOStream,Base.TTY orBase.PipeEndpoint object to represent each stream, e.g.:

$ 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/nullTuple{IOStream,Base.TTY,IOStream}$ echo hello | julia -e 'println(typeof((stdin, stdout, stderr)))' | catTuple{Base.PipeEndpoint,Base.PipeEndpoint,Base.TTY}

TheBase.read andBase.write methods for these streams useccall to call libuv wrappers insrc/jl_uv.c, e.g.:

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

The libuv streams relied upon byjl_printf() etc., are not available until midway through initialization of the runtime (seeinit.c,init_stdio()). Error messages or warnings that need to be printed before this are routed to the standard C libraryfwrite() function by the following mechanism:

Insys.c, theJL_STD* stream pointers are statically initialized to integer constants:STD*_FILENO (0, 1 and 2). Injl_uv.c thejl_uv_puts() function checks itsuv_stream_t* stream argument and callsfwrite() if stream is set toSTDOUT_FILENO orSTDERR_FILENO.

This allows for uniform use ofjl_printf() throughout the runtime regardless of whether or not any particular piece of code is reachable before initialization is complete.

Legacyios.c library

Thesrc/support/ios.c library is inherited fromfemtolisp. It provides cross-platform buffered file IO and in-memory temporary buffers.

ios.c is still used by:

Use ofios.c in these modules is mostly self-contained and separated from the libuv I/O system. However, there isone place where femtolisp calls through tojl_printf() with a legacyios_t stream.

There is a hack inios.h that makes theios_t.bm field line up with theuv_stream_t.type and ensures that the values used forios_t.bm to not overlap with validUV_HANDLE_TYPE values. This allowsuv_stream_t pointers to point toios_t streams.

This is needed becausejl_printf() callerjl_static_show() is passed anios_t stream by femtolisp'sfl_print() function. Julia'sjl_uv_puts() function has special handling for this:

if (stream->type > UV_HANDLE_TYPE_MAX) {    return ios_write((ios_t*)stream, str, n);}

Settings


This document was generated withDocumenter.jl version 1.8.0 onWednesday 9 July 2025. Using Julia version 1.11.6.


[8]ページ先頭

©2009-2025 Movatter.jp