Issue #5677 has been updated by MartinBosslet (Martin Bosslet).


nobu (Nobuyoshi Nakada) wrote:
>
> Can't you use rb_io_stdio_file()?
> And OpenSSL seems providing BIO_new_fd() too.

True, and that's also what I should be using there :) I'll fix it.

> > 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?
> 
> It doesn't seem bad to me.
> 
> They are all added to internal.h by akr.

I've done a lot of IO in C over the last months, now
I have a much clearer picture of it. 

I think my only problem was that there is no unified read/write
that allows working on arbitrary IOs efficiently (I could fall
back to rb_funcall, but then I'd give away the performance benefits).
I had to make the distinction between IOs based on rb_io_t, 
between StringIO and raw Strings. I ended up in writing my own
wrapper that would abstract away the differences. It would be 
really nice to have such an abstraction directly in the API. 
Would this be an option? 
----------------------------------------
Feature #5677: IO C API
https://bugs.ruby-lang.org/issues/5677#change-25512

Author: MartinBosslet (Martin Bosslet)
Status: Assigned
Priority: Normal
Assignee: akr (Akira Tanaka)
Category: core
Target version: 2.0.0


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/