• Places
    • Home
    • Graphs
    • Prefixes
  • Admin
    • Users
    • Settings
    • Plugins
    • Statistics
  • CPACK
    • Home
    • List packs
    • Submit pack
  • Repository
    • Load local file
    • Load from HTTP
    • Load from library
    • Remove triples
    • Clear repository
  • Query
    • YASGUI SPARQL Editor
    • Simple Form
    • SWISH Prolog shell
  • Help
    • Documentation
    • Tutorial
    • Roadmap
    • HTTP Services
  • Login

12.9 Foreign access to Prolog IO streams
AllApplicationManualNameSummaryHelp

  • Documentation
    • Reference manual
      • Foreign Language Interface
        • Foreign access to Prolog IO streams
          • Get IO stream handles
          • Creating an IO stream
            • Snew()
            • Sopen_pipe()
            • Sopenmem()
            • Sfree()
            • PL_unify_stream()
          • Interacting with foreign streams
          • Foreign stream error handling
          • Foreign stream encoding
          • Foreign stream line endings
          • Foreign stream position information
    • Packages
"sec:foreign-create-iostream">12.9.2 Creating an IO stream

A new stream is created using Snew(). Before we can create a stream we must create a function block of type IOFUNCTIONS that provide function pointers for the basic operations on the stream. This type is defined as follows:

typedef struct io_functions
{ Sread_function        read;           /* fill the buffer */
  Swrite_function       write;          /* empty the buffer */
  Sseek_function        seek;           /* seek to position */
  Sclose_function       close;          /* close stream */
  Scontrol_function     control;        /* Info/control */
  Sseek64_function      seek64;         /* seek to position (large files) */
} IOFUNCTIONS;
ssize_t (*Sread_function)(void *handle, char *buf, size_t bufsize)
Read new data into buf that has size bufsize, return the number of bytes read or -1. Note that this is the same interface as the POSIX read() API. See section 12.9.4 for raising errors.
ssize_t (*Swrite_function)(void *handle, char *buf, size_t bufsize)
Write the bytes from buf with contains bufsize bytes and return the number of bytes written or -1. The number of bytes written may be less than bufsize. Bytes that were not written remain in the stream's output buffer. Note that this is the same interface as the POSIX write() API. See section 12.9.4 for raising errors.
long (*Sseek_function)(void *handle, long pos, int whence)
int64_t (*Sseek64_function)(void *handle, int64_t pos, int whence)
Reposition the file pointer. These functions may be NULL if repositioning is not possible on this type or they may return -1 and set errno to EPIPE if the pointer cannot be repositioned on this instance. The function returns the new file position. See Sseek() for details on how repositioning is implemented. See section 12.9.4 for raising errors.
int (*Sclose_function)(void *handle)
Close the stream. This is used by Sclose(). Note that buffered output is first written using the Swrite_function(). See section 12.9.4 for raising errors.
int (*Scontrol_function)(void *handle, int action, void *arg)
Obtain information about the stream or modify the stream. The function should return 0 on success and -1 on failure. If some action is not implemented the function should return -1;
SIO_GETPENDING, size_t*
Return the number of bytes that may be written without blocking. Used by Spending().
SIO_LASTERROR, char*
Called after an error is raised on a stream. May return a C string that sets error details using Sseterr().
SIO_SETENCODING, IOENC*
Called by Ssetenc() to change the encoding of the stream. If the call does not return 0 the encoding is not changed.
SIO_FLUSHOUTPUT, NULL
Called by Sflush() after flushing the stream's output buffer. Note that this is only called on an explicit flush using Sflush() or flush_output/1. An implicit flush because the output buffer is full does not call this hook.
SIO_GETSIZE, int64_t*
Get the size of the underlying object in bytes. Used by Ssize().
SIO_GETFILENO, int*
If the stream is associated with an OS file handle, return this handle. Used by Sfileno().
SIO_GETWINSOCK, SOCKET*
Windows only. If the stream is associated to a Windows socket return this handle. Used by Swinsock().

Given an IOFUNCTIONS block we can create a new stream from a handle using Snew():

IOSTREAM* Snew(void *handle, int flags, IOFUNCTIONS *functions)
Create an IOSTREAM* from a handle, flags and a block of callback functions. The flags argument is a bitwise or of SIO_* flags. Flags that control the creation are:
SIO_INPUT
SIO_OUTPUT
One of these flags mut be present to indicate whether this is an input or output stream.
SIO_NBUF
SIO_LBUF
SIO_FBUF
One of these flags must be present to select the buffering as one of unbuffered (SIO_NBUF), line buffered (SIO_LBUF) or fully buffered (SIO_FBUF)
SIO_TEXT
If given, this is a text stream and the encoding is set to the default encoding (see the Prolog flag encoding). Otherwise this is a binary stream and the encoding is set to ENC_OCTET.
SIO_RECORDPOS
If given, enable position maintenance on the stream. This is used by Stell(), Sseek(), stream_property/2 using the position property and related predicates.
SIO_NOMUTEX
Used internally to create a stream that cannot be owned or locked.

If the stream is associated with an OS file handle the system initializes the SIO_ISATTY flag (on POSIX systems) and if possible tells the OS not to inherit this stream to child processes.

The symbol Sfilefunctions is a IOFUNCTIONS struct that contains the callbacks for accessing a regular file. After opening an file using the POSIX open() API we can create a stream to this file using Snew():

  int fno = open(path, O_RDONLY);
  IOSTREAM *s;

  if ( fno >= 0 )
    s = Snew((void*)fno,
             SIO_INPUT|SIO_FBUF|SIO_RECORDPOS|SIO_TEXT,
             &Sfilefunctions);
  ...

Snew() can only fail if there is not enough memory. In that case the return value is NULL and errno is set to ENOMEM.

IOSTREAM* Sopen_pipe(const char *command, const char *type)
Start a process from command and connect the input or output to the returned stream. This wraps the POSIX popen() API. The type string starts with r or w and may be followed by b to create a binary stream. The default is to create a text stream using the platform conventions and locale.
IOSTREAM* Sopenmem(char **buffer, size_t *sizep, const char *mode)
Open a memory area as a stream. Output streams are automatically resized using realloc() if *size = 0 or the stream is opened with mode "wa". If the buffer is allocated or enlarged, this is achieved using malloc() or realloc(). In this case the returned buffer should be freed by the caller when done. Example:
    { char buf[1024];             // don't allocate for small stuff
      char *s = buf;
      IOSTREAM *fd;
      size_t size = sizeof(buf);

      fd = Sopenmem(&s, &size, "w");
      ...
      Sclose(fd);
      ...
      if ( s != buf )             // appearently moved
        Sfree(s);
    }

The mode is "r" or "w". The mode "rF" calls PL_free(buffer) when closed.

Note: Its is not allowed to access streams created with this call from multiple threads. This is ok for all usage inside Prolog itself. This call is intended to use Sfprintf() and other output functions to create strings.

void Sfree(void *ptr)
This function must be used to free objects that are allocated by the stream interface. Currently this only applies to strings allocated by Sopenmem().

A stream can be made accessible from Prolog using PL_unify_stream():

int PL_unify_stream(term_t t, IOSTREAM *s)
Unify t with a blob that points at s. Note that a blob provides a unique and reliable reference to a stream. Blobs are subject to atom garbage collection. If an open stream is garbage collected the behaviour depends on the Prolog flag agc_close_streams. See also

ClioPatria (version V3.1.1-42-gd6a756b-DIRTY)