On Wed, 7 May 2003, Simon Strandgaard wrote:

> Sorry.. I never thought it would be that hard to explain my problem :-)

this comes up often on the list.  a while back i suggested that IO#redirect,
and friend, should be part of the IO interface and was mostly shrugged off.  i
think a RCR for standard redirection facilities might be a good idea.

> I embed ruby into C++.  The "void main" is located in the frontend.
> Right now everything is running in the same process.
>
> User supplyed ruby-code is executed in the same process...
> its NOT executed as a child-process, thus popen3 is not possible.
> The only thing which is possible right now is the flawed Redirector class
> technique.


i've never run the interpreter from c or c++, but it sure seems like it's
likely that this does an execv, and therefore DOES run in a child process...
i could be wrong here...

> Setting up the redirection will occur within c++!

then you have ONLY one option, which is to do the equivalent of

  ruby script.rb 2>&1 > captured

from within c++ unless

  a) ruby does in fact run in the same process space (not sure about this)
  b) you want to create a StringIO object from within c++, and point defout and
  friends at it before executing user ruby code

because, as i said, i think 'a' is false, you will need to point stderr/stdout
at a file in c++ before running the ruby interpreter.  i really think this is
your only option since even if you were able to set up a StringIO, or other,
object in c++ which could be shared by an in-process ruby - THAT process (the
ruby interpreter) itself could cause a fork either explicily (fork) or
implicitly (backticks or system) which would blow your whole StringIO idea out
of the water.

in summary i think you have only the option of pointing stderr and stdout at a
temporary file, running the user's ruby code from the embedded interpreter,
and then rewinding the file and using that.  however.  i'm with brian that
it's a bad idea to merge stdout and stderr though - i would point stdout to
one temp file and stderr to another.  later, you may decide to do one thing
with the ruby interpreter's stdout and another thing with the stderr.  you may
always merge them manually if you desire.

>
> My setup routine looks like this
>
> void lib_begin() {
> 	if(lib_running)
> 		return;
>
> 	// initialize ruby itself
> 	ruby_init();
> 	ruby_init_loadpath();
> 	ruby_script("embed");
>
> 	// setup our own environment
> 	objects = new RUBY_CPP::Objects;
> 	Redirect::RubyInit();
>
> 	/* ---------------------------
>            todo: setup capture here!
> 	--------------------------- */
>
> 	RUBY_CPP::Require("test");
>
> 	lib_running = true;
> 	cout << "aeditorlib: started (" <<
> 		(use_swig ? "with" : "no") << "-swig)" << endl;
> }

again, this sure looks like the preparation for a fork/execv - or at least a
preparation for something which itself might fork/execv ;-)

-a

--
  ====================================
  | Ara Howard
  | NOAA Forecast Systems Laboratory
  | Information and Technology Services
  | Data Systems Group
  | R/FST 325 Broadway
  | Boulder, CO 80305-3328
  | Email: ara.t.howard / fsl.noaa.gov
  | Phone:  303-497-7238
  | Fax:    303-497-7259
  ====================================