From: "MartinBosslet (Martin Bosslet)" Date: 2012-11-21T11:24:10+09:00 Subject: [ruby-core:49789] [ruby-trunk - Feature #5677] IO C API Issue #5677 has been updated by MartinBosslet (Martin Bosslet). In hindsight, my major concern with current IO C API is the impossibility to optimize something for StringIO. Since StringIO is not part of core, a C extension must typically fall back to calling methods of the Ruby IO API, which is not very efficient. It would be nice to abstract the implementation details away, calling C API methods that take care of the details and efficiency - but I agree, that would be a lot of work. But still, is a revised IO API possible in the future? I think IO-heavy C extensions would almost certainly benefit from it. ---------------------------------------- Feature #5677: IO C API https://bugs.ruby-lang.org/issues/5677#change-33370 Author: MartinBosslet (Martin Bosslet) Status: Assigned Priority: Normal Assignee: akr (Akira Tanaka) Category: core Target version: next minor This is related to the proposal in [ruby-core:41321][1]. I'd like to take advantage of streaming IO in an extension I am working on. The problem I'm having is that I don't want to call IO#read on the rb_funcall level because that would kill the performance due to wrapping the bytes into Ruby objects back and forth again. I saw two solutions to my problem: 1. Duplicating the file descriptor to obtain a pure FILE* like it is done in ext/openssl/ossl_bio.c[2] and continue working on the raw FILE*. 2. Since I really only need to read and write on the stream, I was looking for public Ruby C API that would support me in the process, and I found - ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size) - ssize_t rb_io_bufread(VALUE io, void *buf, size_t size) I think both cases are valid use cases, 1. is likely necessary if there is the need to pass a FILE* on to an external C library, 2. is for cases like mine where there is the need to operate on raw C data types for performance reasons. The problem, though, is that only rb_io_bufwrite is public API in io.h, rb_io_bufread is declared private in internal.h and rb_cloexec_dup is semi-public in intern.h. Could we make rb_io_bufread public API in io.h as well? What about rb_cloexec_dup? [1] http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/41321 [2] https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_bio.c#L17 -- http://bugs.ruby-lang.org/