Redirect stdout, stderr to string/stream C++ (embedded)

Hi,

I am currently a newbie on julia

I try to redirect all outputs stderr, stdout to C/C++ from julia
Currently I do and it seems to work:

         # Create custom IO buffer
         const io = IOBuffer()
         Base.stdout = io;
         # Define function to retrieve buffer contents
         function get_output()
             return String(take!(copy(io)))
         end
        
         # Define function to clear buffer
         function clear_output()
             truncate(io, 0)
         end
jl_eval_string("clear_output()");
jl_eval_string("println(1+1)");
jl_value_t* output = jl_eval_string("get_output()");
if (output)
{
   std::string txt = std::string(jl_string_ptr(output));
   io->outputMessage(txt); // my internal output
}

result is correctly displayed.

But if I do:

jl_eval_string("1+1");

result of stdout is not in available

I did not found how to redirect this case to a C/C++ stream too

Any advice is welcome

Thanks for your help

What would you expect in stdout from evaluating 1+1? It doesn’t print anything.

(When you enter an expression at the interactive julia> REPL prompt, it calls display on the result of the expression, which outputs it to stdout. But this isn’t done for expressions evaluated with jl_eval_string.)

Note that a more robust way to redirect stdout to a String is to use redirect_stdout, see e.g. Jupyter notebook capture stdout and stderr like python capture magic? - #4 by stevengj

PS. I fixed the formatting in your post, but for the future please read: PSA: how to quote code with backticks

Yes, I would like also redirect display output into stdout to have in a std::string

Just re-assigning Base.stdout or calling redirect won’t accomplish this, because the default display backend saves a reference to the original stdout. (Also, the whole point of display is that the output can be specific to your enviroment, e.g. some objects might display graphically in Jupyter or Pluto or similar environments.)

The right way to capture display output is to call pushdisplay to push a new display backend to the top of the stack — this will get called first for any code that invokes display(x), allowing you to do whatever you want, displaying objects as text or other supported formats as desired, or capturing the output in a string or array. This is what IJulia does, for example. It’s also what Pluto.jl does.

However, I want to step back a bit. Why are you doing this? Are you creating a new interactive environment for Julia? If not, i.e. for non-interactive use, I wouldn’t recommend communicating with libjulia via strings, and especially not by capturing stdout — better to pass data back and forth directly, in native formats.

Thank you for the help! Let me clarify my goals a bit. I’m exploring this approach as part of building a new environment between Nelson and Julia, where the focus is on enabling seamless integration. My aim is to create a bridge that provides an accessible and user-friendly experience for Nelson’s users who might not be familiar with Julia.

Using strings and capturing stdout is primarily a convenience for this early stage of development, allowing for rapid prototyping and easier debugging.

If you have any specific recommendations or examples of best practices for interfacing with libjulia, I’d love to hear them!

Currently I investigate to do equivalent of python_engine already available in Nelson (equivalent to matlab feature)
I did not add a link on help file of Nelson, since I currently not allowed to add url in comments …

R = jlrun(‘A = 1+ 2’, ‘A’)
will return in R value of A

I also expected to have jlrun(‘1+ 2’) print as REPL ie ‘3’

You don’t have to print to stdout, capture that and send back the string for getting repl-like output about results of your expressions. The repr function for example returns a string that should be similar to what the repl prints, you could just call that on the resulting value.

1 Like

Thanks !!!
If you are curious see here
existing python engine in Nelson

Are you trying to provide a REPL like interface where users can run arbitrary commands?