AnyMath 文档

Julia运行时中的printf()和stdio

用于stdio的Libuv包装器

朱莉娅。h 定义https://docs.libuv.org[libuv]包装 斯蒂迪奥。h 溪涧:

uv_stream_t *JL_STDIN;
uv_stream_t *JL_STDOUT;
uv_stream_t *JL_STDERR;
  1. 及相应的输出功能:

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

这些 printf打印 函数由 .c 文件在 src公司/cli/ 需要stdio的目录,以确保以统一的方式处理输出缓冲。

在特殊情况下,如信号处理程序,其中完整的libuv基础设施太重, jl_safe_printf() 可用于 写(2)直接到 STDERR_菲勒诺:

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

JL_STD*和Julia代码之间的接口

基地。标准普尔, 基地。标准输出基地。斯德尔JL_STD* 运行时中定义的libuv流。

朱莉娅的 __init__() 功能(在 基地/sysimg。jl)电话 reinit_stdio() (在 基/流。jl)创建Julia对象 基地。标准普尔, 基地。标准输出基地。斯德尔. reinit_stdio() 用途 ccall检索指向 JL_STD* 和电话 jl_uv_handle_type() 来检查每个流的类型。 然后它创建了一个Julia 基地。[美]梦, 基地。TTY缧基地。管点,管点 对象来表示每个流,例如:

$ 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}

基地。讀!基地。写这些流的方法使用 ccall调用libuv包装器 src/jl_uv。c,例如:

stream.jl: function write(s::IO, p::Ptr, nb::Integer)
               -> ccall(:jl_uv_write, ...)
  jl_uv.c:          -> int jl_uv_write(uv_stream_t &ast;stream, ...)
                        -> uv_write(uvw, stream, buf, ...)

初始化过程中的printf()

Libuv流依赖于 jl_printf() 等。,直到运行时初始化中途才可用(请参阅 初始化。c, init_stdio()). 在路由到标准C库之前需要打印的错误消息或警告 fwrite() 通过以下机制发挥作用:

系统。c,的 JL_STD* 流指针静态初始化为整数常量: STD*_FILENO(0,1和2). 在 jl_uv。cjl_uv_puts() 功能检查其 uv_stream_t*流 参数和调用 fwrite() 如果流设置为 STDOUT_FILENOSTDERR_菲勒诺.

这允许统一使用 jl_printf() 在整个运行时,无论在初始化完成之前是否可以访问任何特定的代码片段。

遗产 的ios。c 图书馆

src/支持/ios。c 库继承自https://github.com/JeffBezanson/femtolisp[femtolisp].它提供跨平台缓冲文件IO和内存中的临时缓冲区。

的ios。c 仍然被使用:

* src/flisp/*。c * src/转储。c --用于序列化文件IO和用于内存缓冲区。 * src/staticdata。c --用于序列化文件IO和用于内存缓冲区。 * 基地/iostream.jl --对于文件IO(见 基/fs。jl 为libuv等价物)。

使用 ios的。c 在这些模块大多是自包含和分离的libuv I/O系统。 但是,有https://github.com/JuliaLang/julia/blob/master/src/flisp/print.c#L654[一个地方]femtolisp打电话到 jl_printf() 带着遗产 ios_t 小溪。

有一个黑客在 的ios。h 这使得 ios_t.bm 场排队与 uv_stream_t.类型 并确保用于 ios_t.bm 不与有效重叠 UV_HANDLE_TYPE 价值观。 这允许 uv_stream_t 指向的指针 ios_t 溪流。

这是必要的,因为 jl_printf() 来电者 jl_static_show() 通过 ios_t 由femtolisp的流 fl_print() 函数。 朱莉娅的 jl_uv_puts() 函数对此有特殊处理:

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