Julia运行时环境中的printf()和stdio
用于stdio的libuv壳
"朱莉娅。h’定义贝壳https://docs.libuv.org [libuv]为`stdio。h’溪水:
uv_stream_t *JL_STDIN;
uv_stream_t *JL_STDOUT;
uv_stream_t *JL_STDERR;
及相应的输出功能:
int jl_printf(uv_stream_t *s, const char *format, ...);
int jl_vprintf(uv_stream_t *s, const char *format, va_list args);
这些’printf’函数由`使用。在`src/`和`cli/`目录中的c’文件,只要stdio需要提供统一的输出缓冲。
在特殊情况下,例如,当使用信号处理程序时,当完整的libuv基础结构太大时,可以使用`jl_safe_printf()'函数来写入(write(2)
)直接在’STDERR_FILENO’中。
void jl_safe_printf(const char *str, ...);
JL_STD*和Julia代码之间的接口
常量 '基地。stdin', '基地。stdout'和 '基地。stderr'绑定到运行时环境中定义的libuv’JL_STD*'线程。
Julia'__init__()函数'(在’base/sysimg.jl')调用’reinit_stdio()(in’base/stream.jl
)为常量创建Julia对象 '基地。stdin', '基地。stdout'和 '基地。stderr'。
函数’reinit_stdio()`使用关键字 'ccall'获取指向流的指针’JL_STD*'并调用’jl_uv_handle_type()'来检查每个流的类型。 然后她创建了Julia对象的基础。IOStream','基地。TTY’或’基地。PipeEndpoint’来表示每个流,例如:
$ 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}
方法 '基地。阅读'和 '基地。write'关键字用于这些流 ccall
在’src/jl_uv中调用libuv shell。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 *stream, ...) -> uv_write(uvw, stream, buf, ...)
初始化过程中的printf()
由函数`jl_printf()等依赖的libuv流在运行时初始化中期之前不可用(参见`init’的描述。c','init_stdio()
)。 在到达此点之前应显示的错误消息或警告使用以下机制发送到C标准库的’fwrite()`函数。
在系统里。c`,流指针’JL_STD*'静态初始化为整数常量:'STD*_FILENO(0,1和2)'。 在’jl_uv。c’函数’jl_uv_puts()'检查其参数’uv_stream_t*stream’并调用’fwrite()'如果流具有值’STDOUT_FILENO’或’STDERR_FILENO`
这允许在整个执行时间内统一使用`jl_printf()`函数,而不考虑初始化完成之前任何特定代码段的可用性。
过时的库’ios.c`
库’src/support/ios。c’继承自https://github.com/JeffBezanson/femtolisp [femtolisp]。 它提供跨平台缓冲文件I/O,并在内存中提供临时缓冲区。
'ios。c’仍然被以下文件使用。
-
'src/flisp/*。c`
-
'src/转储。c'--用于序列化文件I/O和内存中的缓冲区。
-
'src/staticdata。c'--用于序列化文件I/O和内存中的缓冲区。
-
'基地/iostream。jl'--对于文件I/O(参见’base/fs。jl`根据libuv等价物)。
使用’ios。这些模块中的C`大多是自包含的,并且与libuv I/O系统分开发生。 但是,有https://github.com/JuliaLang/julia/blob/master/src/flisp/print.c#L654 [一个地方]其中femtolisp用过时的`ios_t`线程调用`jl_printf()`。
在’ios。h’有一个附加字段的工具`ios_t.bm 'to’uv_stream_t.type’并确保用于`ios_t.bm `,不会与`UV_HANDLE_TYPE’的有效值重叠。 这允许`uv_stream_t’指针指向’ios_t’流。
这是必要的,因为`fl_print()'femtolisp函数将’ios_t`流传递给`jl_printf()函数,该函数调用`jl_static_show()
。 Julia中的`jl_uv_puts()'函数以特殊的方式处理这一刻。
if (stream->type > UV_HANDLE_TYPE_MAX) {
return ios_write((ios_t*)stream, str, n);
}