Capture standard output from write\1 predicate in C++

Hey, it’s me again. I’m currently looking for a way to capture an output from a write\1, so I can manipulate the string as I want.
Here is the example:

PlCall("assert", PlTermv(PlCompound("myprint :- write('soy un poco loco')")));
PlCall("myprint");

With this code I get the standard output in my cmd with the string:

soy un poco loco

But I want, for example, put it in a string and manipulate it without using standard output redirection if possible

I guess the simplest is to call with_output_to/2, as in

 with_output_to(string(S), Goal).

To make it simpler, define in your Prolog file e.g.,

:- meta_predicate capture_in_string(-,0).
capture_in_string(S, Goal) :- with_output_to(string(S), Goal).

This should capture all output written to current_output

2 Likes

The generic C++ interface to streams is PlStream, but it’s a fairly thin wrapper on the C API.

If you want a stream for writing to memory, see Sopenmem() – there’s an example of its use in packages/odbc/ofbc.c. You can convert the IOSTREAM* to a PlStream. See also PlAcquireStream.

(I’ve wanted this a few times, so maybe it’s worthwhile making a nice C++ API for writing to a string.)

1 Like

I’m not sure. There may be exceptions, but in general you do not want to exchange text when combining Prolog with some other language.

Playing around with the standard streams is rather tricky, so possibly using with_output_to/2 is a good idea anyway … You already have to call Prolog anyway. The main reason to do it from C++ might be if there is a huge amount of output to be captured, i.e., more than what fits on the Prolog stack.

1 Like

This helped me out a lot, I added this to the bottom of the knowledge base and, after that, I added this code to my C++ testing project

openPrologFile("planTest");
PlTermv theTest(2);
theTest[1].unify_atom("test");
PlQuery theQuery("capture_in_string", theTest);
try {
    PlCheckFail(theQuery.next_solution());
    cout << "solution:\n" << theTest[0].as_string() << "\n";
}
catch (PlFail f) {
    cerr << "err\n";
}

And it worked!
Don’t pay attention to openPrologFile, it’s just a quick procedure I added to quickly prompt PlCall("consult",...) with exception handling.