There are several ways to get access to an IO Stream handle, 
basically get them from Prolog, get access to the standard streams and 
create a new stream. The standard streams are available as
Sinput, Soutput and Serror. Note 
that these are thread specific. Creating a new stream is discussed with Snew(). 
Below are the functions to obtain a stream handle from a Prolog term, 
obtain and release ownership.
TRUE 
on success and FALSE on failure, by default generating an 
exception. The flags argument is a bitwise disjunction of 
these flags:
SIO_INPUTSIO_OUTPUTSIO_INPUT for details. 
If neither SIO_OUTPUT nor SIO_INPUT is given t 
may not be a pair.SIO_TRYLOCKFALSE if the stream cannot be locked immediately. No 
error is generated.SIO_NOERRORThe returned stream is owned by the calling thread using PL_acquire_stream().
atom_t object rather than a IOSTREAM*.FALSE with an 
exception. Otherwise return TRUE.
In general, stream functions do not set any Prolog error state; that 
is done by PL_release_stream(). 
Once a stream is in an error state, all subsequent functions act as 
no-ops (returning -1) unless Sclearerr() 
is called. Sferror() 
may be used to check whether a stream is in an error condition. This 
error may be turned into a Prolog exception by calling
PL_acquire_stream() 
followed by PL_release_stream(). 
In this case,
PL_release_stream() 
will set the Prolog exception and return
FALSE.
Below is an example that writes “Hello World” to a stream provided by Prolog. Note that PL_release_stream() raises an exception if the Sfprintf() failed and (thus) left the stream in an error state.
static foreign_t
hello_world(term_t to)
{ IOSTREAM *s;
  if ( PL_get_stream(to, &s, SIO_OUTPUT) )
  { Sfprintf(s, "Hello World!\n");
    return PL_release_stream(s);
  }
  return FALSE;
}
  ... // fragment from install function
  PL_register_foreign("hello world", 1, hello_world, 0);