(*
################################################################################
#  THIS FILE IS 100% GENERATED BY ZPROJECT; DO NOT EDIT EXCEPT EXPERIMENTALLY  #
#  Read the zproject/README.md for information about making permanent changes. #
################################################################################
*)

unit CZMQ;

interface

uses
  libczmq, Winapi.Windows, Winapi.Winsock2;

// forward declarations
 type
  IZactor = interface;
  IZarmour = interface;
  IZcert = interface;
  IZcertstore = interface;
  IZchunk = interface;
  IZconfig = interface;
  IZdigest = interface;
  IZdir = interface;
  IZdirPatch = interface;
  IZfile = interface;
  IZframe = interface;
  IZhash = interface;
  IZhashx = interface;
  IZiflist = interface;
  IZlist = interface;
  IZlistx = interface;
  IZloop = interface;
  IZmsg = interface;
  IZpoller = interface;
  IZsock = interface;
  IZuuid = interface;

  // provides a simple actor framework
  IZactor = interface

    // Send a zmsg message to the actor, take ownership of the message
    // and destroy when it has been sent.
    function Send(var MsgP: IZmsg): Integer;

    // Receive a zmsg message from the actor. Returns NULL if the actor
    // was interrupted before the message could be received, or if there
    // was a timeout on the actor.
    function Recv: IZmsg;

    // Return the actor's zsock handle. Use this when you absolutely need
    // to work with the zsock instance rather than the actor.
    function Sock: IZsock;

    // Change default destructor by custom function. Actor MUST be able to handle new message instead of default $TERM.
    procedure SetDestructor(&Destructor: TZactorDestructorFn);
  end;

  // armoured text encoding and decoding
  IZarmour = interface

    // Encode a stream of bytes into an armoured string. Returns the armoured
    // string, or NULL if there was insufficient memory available to allocate
    // a new string.
    function Encode(Data: PByte; Size: NativeUInt): string;

    // Decode an armoured string into a chunk. The decoded output is
    // null-terminated, so it may be treated as a string, if that's what
    // it was prior to encoding.
    function Decode(const Data: string): IZchunk;

    // Get the mode property.
    function Mode: Integer;

    // Get printable string for mode.
    function ModeStr: string;

    // Set the mode property.
    procedure SetMode(Mode: Integer);

    // Return true if padding is turned on.
    function Pad: Boolean;

    // Turn padding on or off. Default is on.
    procedure SetPad(Pad: Boolean);

    // Get the padding character.
    function PadChar: AnsiChar;

    // Set the padding character.
    procedure SetPadChar(PadChar: AnsiChar);

    // Return if splitting output into lines is turned on. Default is off.
    function LineBreaks: Boolean;

    // Turn splitting output into lines on or off.
    procedure SetLineBreaks(LineBreaks: Boolean);

    // Get the line length used for splitting lines.
    function LineLength: NativeUInt;

    // Set the line length used for splitting lines.
    procedure SetLineLength(LineLength: NativeUInt);

    // Print properties of object
    procedure Print;
  end;

  // work with CURVE security certificates
  IZcert = interface

    // Return public part of key pair as 32-byte binary string
    function PublicKey: PByte;

    // Return secret part of key pair as 32-byte binary string
    function SecretKey: PByte;

    // Return public part of key pair as Z85 armored string
    function PublicTxt: string;

    // Return secret part of key pair as Z85 armored string
    function SecretTxt: string;

    // Set certificate metadata from formatted string.
    procedure SetMeta(const Name: string; const Format: string);

    // Unset certificate metadata.
    procedure UnsetMeta(const Name: string);

    // Get metadata value from certificate; if the metadata value doesn't
    // exist, returns NULL.
    function Meta(const Name: string): string;

    // Get list of metadata fields from certificate. Caller is responsible for
    // destroying list. Caller should not modify the values of list items.
    function MetaKeys: IZlist;

    // Save full certificate (public + secret) to file for persistent storage
    // This creates one public file and one secret file (filename + "_secret").
    function Save(const Filename: string): Integer;

    // Save public certificate only to file for persistent storage
    function SavePublic(const Filename: string): Integer;

    // Save secret certificate only to file for persistent storage
    function SaveSecret(const Filename: string): Integer;

    // Apply certificate to socket, i.e. use for CURVE security on socket.
    // If certificate was loaded from public file, the secret key will be
    // undefined, and this certificate will not work successfully.
    procedure Apply(const Socket: IZSock);

    // Return copy of certificate; if certificate is NULL or we exhausted
    // heap memory, returns NULL.
    function Dup: IZcert;

    // Return true if two certificates have the same keys
    function Eq(const Compare: IZcert): Boolean;

    // Print certificate contents to stdout
    procedure Print;
  end;

  // work with CURVE security certificate stores
  IZcertstore = interface

    // Override the default disk loader with a custom loader fn.
    procedure SetLoader(Loader: TZcertstoreLoader; &Destructor: TZcertstoreDestructor; State: PByte);

    // Look up certificate by public key, returns zcert_t object if found,
    // else returns NULL. The public key is provided in Z85 text format.
    function Lookup(const PublicKey: string): IZcert;

    // Insert certificate into certificate store in memory. Note that this
    // does not save the certificate to disk. To do that, use zcert_save()
    // directly on the certificate. Takes ownership of zcert_t object.
    procedure Insert(var CertP: IZcert);

    // Empty certificate hashtable. This wrapper exists to be friendly to bindings,
    // which don't usually have access to struct internals.
    procedure Empty;

    // Print list of certificates in store to logging facility
    procedure Print;

    // Return a list of all the certificates in the store.
    // The caller takes ownership of the zlistx_t object and is responsible
    // for destroying it.  The caller does not take ownership of the zcert_t
    // objects.
    function Certs: IZlistx;
  end;

  // work with memory chunks
  IZchunk = interface

    // Resizes chunk max_size as requested; chunk_cur size is set to zero
    procedure Resize(Size: NativeUInt);

    // Return chunk cur size
    function Size: NativeUInt;

    // Return chunk max size
    function MaxSize: NativeUInt;

    // Return chunk data
    function Data: PByte;

    // Set chunk data from user-supplied data; truncate if too large. Data may
    // be null. Returns actual size of chunk
    function &Set(Data: PByte; Size: NativeUInt): NativeUInt;

    // Fill chunk data from user-supplied octet
    function Fill(Filler: Byte; Size: NativeUInt): NativeUInt;

    // Append user-supplied data to chunk, return resulting chunk size. If the
    // data would exceeded the available space, it is truncated. If you want to
    // grow the chunk to accommodate new data, use the zchunk_extend method.
    function Append(Data: PByte; Size: NativeUInt): NativeUInt;

    // Append user-supplied data to chunk, return resulting chunk size. If the
    // data would exceeded the available space, the chunk grows in size.
    function Extend(Data: PByte; Size: NativeUInt): NativeUInt;

    // Copy as much data from 'source' into the chunk as possible; returns the
    // new size of chunk. If all data from 'source' is used, returns exhausted
    // on the source chunk. Source can be consumed as many times as needed until
    // it is exhausted. If source was already exhausted, does not change chunk.
    function Consume(const Source: IZchunk): NativeUInt;

    // Returns true if the chunk was exhausted by consume methods, or if the
    // chunk has a size of zero.
    function Exhausted: Boolean;

    // Write chunk to an open file descriptor
    function Write(Handle: Pointer): Integer;

    // Create copy of chunk, as new chunk object. Returns a fresh zchunk_t
    // object, or null if there was not enough heap memory. If chunk is null,
    // returns null.
    function Dup: IZchunk;

    // Return chunk data encoded as printable hex string. Caller must free
    // string when finished with it.
    function Strhex: string;

    // Return chunk data copied into freshly allocated string
    // Caller must free string when finished with it.
    function Strdup: string;

    // Return TRUE if chunk body is equal to string, excluding terminator
    function Streq(const &String: string): Boolean;

    // Transform zchunk into a zframe that can be sent in a message.
    function Pack: IZframe;

    // Calculate SHA1 digest for chunk, using zdigest class.
    function Digest: string;

    // Dump chunk to FILE stream, for debugging and tracing.
    procedure Fprint(&File: Pointer);

    // Dump message to stderr, for debugging and tracing.
    // See zchunk_fprint for details
    procedure Print;
  end;

  // work with config files written in rfc.zeromq.org/spec:4/ZPL.
  IZconfig = interface

    // Create copy of zconfig, caller MUST free the value
    // Create copy of config, as new zconfig object. Returns a fresh zconfig_t
    // object. If config is null, or memory was exhausted, returns null.
    function Dup: IZconfig;

    // Return name of config item
    function Name: string;

    // Return value of config item
    function Value: string;

    // Insert or update configuration key with value
    procedure Put(const Path: string; const Value: string);

    // Equivalent to zconfig_put, accepting a format specifier and variable
    // argument list, instead of a single string value.
    procedure Putf(const Path: string; const Format: string);

    // Get value for config item into a string value; leading slash is optional
    // and ignored.
    function Get(const Path: string; const DefaultValue: string): string;

    // Set config item name, name may be NULL
    procedure SetName(const Name: string);

    // Set new value for config item. The new value may be a string, a printf
    // format, or NULL. Note that if string may possibly contain '%', or if it
    // comes from an insecure source, you must use '%s' as the format, followed
    // by the string.
    procedure SetValue(const Format: string);

    // Find our first child, if any
    function Child: IZconfig;

    // Find our first sibling, if any
    function Next: IZconfig;

    // Find a config item along a path; leading slash is optional and ignored.
    function Locate(const Path: string): IZconfig;

    // Locate the last config item at a specified depth
    function AtDepth(Level: Integer): IZconfig;

    // Execute a callback for each config item in the tree; returns zero if
    // successful, else -1.
    function Execute(Handler: TZconfigFct; Arg: Pointer): Integer;

    // Add comment to config item before saving to disk. You can add as many
    // comment lines as you like. If you use a null format, all comments are
    // deleted.
    procedure SetComment(const Format: string);

    // Return comments of config item, as zlist.
    function Comments: IZlist;

    // Save a config tree to a specified ZPL text file, where a filename
    // "-" means dump to standard output.
    function Save(const Filename: string): Integer;

    // Equivalent to zconfig_save, taking a format string instead of a fixed
    // filename.
    function Savef(const Format: string): Integer;

    // Report filename used during zconfig_load, or NULL if none
    function Filename: string;

    // Save a config tree to a new memory chunk
    function ChunkSave: IZchunk;

    // Save a config tree to a new null terminated string
    function StrSave: string;

    // Return true if a configuration tree was loaded from a file and that
    // file has changed in since the tree was loaded.
    function HasChanged: Boolean;

    // Destroy subtree (all children)
    procedure RemoveSubtree;

    // Print the config file to open stream
    procedure Fprint(&File: Pointer);

    // Print properties of object
    procedure Print;
  end;

  // provides hashing functions (SHA-1 at present)
  IZdigest = interface

    // Add buffer into digest calculation
    procedure Update(Buffer: PByte; Length: NativeUInt);

    // Return final digest hash data. If built without crypto support,
    // returns NULL.
    function Data: PByte;

    // Return final digest hash size
    function Size: NativeUInt;

    // Return digest as printable hex string; caller should not modify nor
    // free this string. After calling this, you may not use zdigest_update()
    // on the same digest. If built without crypto support, returns NULL.
    function &String: string;
  end;

  // work with file-system directories
  IZdir = interface

    // Return directory path
    function Path: string;

    // Return last modification time for directory.
    function Modified: Int64;

    // Return total hierarchy size, in bytes of data contained in all files
    // in the directory tree.
    function Cursize: Longint;

    // Return directory count
    function Count: NativeUInt;

    // Returns a sorted list of zfile objects; Each entry in the list is a pointer
    // to a zfile_t item already allocated in the zdir tree. Do not destroy the
    // original zdir tree until you are done with this list.
    function List: IZlist;

    // Remove directory, optionally including all files that it contains, at
    // all levels. If force is false, will only remove the directory if empty.
    // If force is true, will remove all files and all subdirectories.
    procedure Remove(Force: Boolean);

    // Return full contents of directory as a zdir_patch list.
    function Resync(const Alias: string): IZlist;

    // Load directory cache; returns a hash table containing the SHA-1 digests
    // of every file in the tree. The cache is saved between runs in .cache.
    function Cache: IZhash;

    // Print contents of directory to open stream
    procedure Fprint(&File: Pointer; Indent: Integer);

    // Print contents of directory to stdout
    procedure Print(Indent: Integer);
  end;

  // work with directory patches
  IZdirPatch = interface

    // Create copy of a patch. If the patch is null, or memory was exhausted,
    // returns null.
    function Dup: IZdirPatch;

    // Return patch file directory path
    function Path: string;

    // Return patch file item
    function &File: IZfile;

    // Return operation
    function Op: Integer;

    // Return patch virtual file path
    function Vpath: string;

    // Calculate hash digest for file (create only)
    procedure DigestSet;

    // Return hash digest for patch file
    function Digest: string;
  end;

  // helper functions for working with files.
  IZfile = interface

    // Duplicate a file item, returns a newly constructed item. If the file
    // is null, or memory was exhausted, returns null.
    function Dup: IZfile;

    // Return file name, remove path if provided
    function Filename(const Path: string): string;

    // Refresh file properties from disk; this is not done automatically
    // on access methods, otherwise it is not possible to compare directory
    // snapshots.
    procedure Restat;

    // Return when the file was last modified. If you want this to reflect the
    // current situation, call zfile_restat before checking this property.
    function Modified: Int64;

    // Return the last-known size of the file. If you want this to reflect the
    // current situation, call zfile_restat before checking this property.
    function Cursize: Longint;

    // Return true if the file is a directory. If you want this to reflect
    // any external changes, call zfile_restat before checking this property.
    function IsDirectory: Boolean;

    // Return true if the file is a regular file. If you want this to reflect
    // any external changes, call zfile_restat before checking this property.
    function IsRegular: Boolean;

    // Return true if the file is readable by this process. If you want this to
    // reflect any external changes, call zfile_restat before checking this
    // property.
    function IsReadable: Boolean;

    // Return true if the file is writeable by this process. If you want this
    // to reflect any external changes, call zfile_restat before checking this
    // property.
    function IsWriteable: Boolean;

    // Check if file has stopped changing and can be safely processed.
    // Updates the file statistics from disk at every call.
    function IsStable: Boolean;

    // Return true if the file was changed on disk since the zfile_t object
    // was created, or the last zfile_restat() call made on it.
    function HasChanged: Boolean;

    // Remove the file from disk
    procedure Remove;

    // Open file for reading
    // Returns 0 if OK, -1 if not found or not accessible
    function Input: Integer;

    // Open file for writing, creating directory if needed
    // File is created if necessary; chunks can be written to file at any
    // location. Returns 0 if OK, -1 if error.
    function Output: Integer;

    // Read chunk from file at specified position. If this was the last chunk,
    // sets the eof property. Returns a null chunk in case of error.
    function Read(Bytes: NativeUInt; Offset: Longint): IZchunk;

    // Returns true if zfile_read() just read the last chunk in the file.
    function Eof: Boolean;

    // Write chunk to file at specified position
    // Return 0 if OK, else -1
    function Write(const Chunk: IZchunk; Offset: Longint): Integer;

    // Read next line of text from file. Returns a pointer to the text line,
    // or NULL if there was nothing more to read from the file.
    function Readln: string;

    // Close file, if open
    procedure Close;

    // Return file handle, if opened
    function Handle: Pointer;

    // Calculate SHA1 digest for file, using zdigest class.
    function Digest: string;
  end;

  // working with single message frames
  IZframe = interface

    // Return number of bytes in frame data
    function Size: NativeUInt;

    // Return address of frame data
    function Data: PByte;

    // Return meta data property for frame
    // The caller shall not modify or free the returned value, which shall be
    // owned by the message.
    function Meta(const &Property: string): string;

    // Create a new frame that duplicates an existing frame. If frame is null,
    // or memory was exhausted, returns null.
    function Dup: IZframe;

    // Return frame data encoded as printable hex string, useful for 0MQ UUIDs.
    // Caller must free string when finished with it.
    function Strhex: string;

    // Return frame data copied into freshly allocated string
    // Caller must free string when finished with it.
    function Strdup: string;

    // Return TRUE if frame body is equal to string, excluding terminator
    function Streq(const &String: string): Boolean;

    // Return frame MORE indicator (1 or 0), set when reading frame from socket
    // or by the zframe_set_more() method
    function More: Integer;

    // Set frame MORE indicator (1 or 0). Note this is NOT used when sending
    // frame to socket, you have to specify flag explicitly.
    procedure SetMore(More: Integer);

    // Return frame routing ID, if the frame came from a ZMQ_SERVER socket.
    // Else returns zero.
    function RoutingId: Cardinal;

    // Set routing ID on frame. This is used if/when the frame is sent to a
    // ZMQ_SERVER socket.
    procedure SetRoutingId(RoutingId: Cardinal);

    // Return frame group of radio-dish pattern.
    function Group: string;

    // Set group on frame. This is used if/when the frame is sent to a
    // ZMQ_RADIO socket.
    // Return -1 on error, 0 on success.
    function SetGroup(const Group: string): Integer;

    // Return TRUE if two frames have identical size and data
    // If either frame is NULL, equality is always false.
    function Eq(const Other: IZframe): Boolean;

    // Set new contents for frame
    procedure Reset(Data: PByte; Size: NativeUInt);

    // Send message to zsys log sink (may be stdout, or system facility as
    // configured by zsys_set_logstream). Prefix shows before frame, if not null.
    procedure Print(const Prefix: string);
  end;

  // generic type-free hash container (simple)
  IZhash = interface

    // Insert item into hash table with specified key and item.
    // If key is already present returns -1 and leaves existing item unchanged
    // Returns 0 on success.
    function Insert(const Key: string; Item: Pointer): Integer;

    // Update item into hash table with specified key and item.
    // If key is already present, destroys old item and inserts new one.
    // Use free_fn method to ensure deallocator is properly called on item.
    procedure Update(const Key: string; Item: Pointer);

    // Remove an item specified by key from the hash table. If there was no such
    // item, this function does nothing.
    procedure Delete(const Key: string);

    // Return the item at the specified key, or null
    function Lookup(const Key: string): Pointer;

    // Reindexes an item from an old key to a new key. If there was no such
    // item, does nothing. Returns 0 if successful, else -1.
    function Rename(const OldKey: string; const NewKey: string): Integer;

    // Set a free function for the specified hash table item. When the item is
    // destroyed, the free function, if any, is called on that item.
    // Use this when hash items are dynamically allocated, to ensure that
    // you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
    // Returns the item, or NULL if there is no such item.
    function Freefn(const Key: string; FreeFn: TZhashFreeFn): Pointer;

    // Return the number of keys/items in the hash table
    function Size: NativeUInt;

    // Make copy of hash table; if supplied table is null, returns null.
    // Does not copy items themselves. Rebuilds new table so may be slow on
    // very large tables. NOTE: only works with item values that are strings
    // since there's no other way to know how to duplicate the item value.
    function Dup: IZhash;

    // Return keys for items in table
    function Keys: IZlist;

    // Simple iterator; returns first item in hash table, in no given order,
    // or NULL if the table is empty. This method is simpler to use than the
    // foreach() method, which is deprecated. To access the key for this item
    // use zhash_cursor(). NOTE: do NOT modify the table while iterating.
    function First: Pointer;

    // Simple iterator; returns next item in hash table, in no given order,
    // or NULL if the last item was already returned. Use this together with
    // zhash_first() to process all items in a hash table. If you need the
    // items in sorted order, use zhash_keys() and then zlist_sort(). To
    // access the key for this item use zhash_cursor(). NOTE: do NOT modify
    // the table while iterating.
    function Next: Pointer;

    // After a successful first/next method, returns the key for the item that
    // was returned. This is a constant string that you may not modify or
    // deallocate, and which lasts as long as the item in the hash. After an
    // unsuccessful first/next, returns NULL.
    function Cursor: string;

    // Add a comment to hash table before saving to disk. You can add as many
    // comment lines as you like. These comment lines are discarded when loading
    // the file. If you use a null format, all comments are deleted.
    procedure Comment(const Format: string);

    // Serialize hash table to a binary frame that can be sent in a message.
    // The packed format is compatible with the 'dictionary' type defined in
    // http://rfc.zeromq.org/spec:35/FILEMQ, and implemented by zproto:
    //
    //    ; A list of name/value pairs
    //    dictionary      = dict-count *( dict-name dict-value )
    //    dict-count      = number-4
    //    dict-value      = longstr
    //    dict-name       = string
    //
    //    ; Strings are always length + text contents
    //    longstr         = number-4 *VCHAR
    //    string          = number-1 *VCHAR
    //
    //    ; Numbers are unsigned integers in network byte order
    //    number-1        = 1OCTET
    //    number-4        = 4OCTET
    //
    // Comments are not included in the packed data. Item values MUST be
    // strings.
    function Pack: IZframe;

    // Save hash table to a text file in name=value format. Hash values must be
    // printable strings; keys may not contain '=' character. Returns 0 if OK,
    // else -1 if a file error occurred.
    function Save(const Filename: string): Integer;

    // Load hash table from a text file in name=value format; hash table must
    // already exist. Hash values must printable strings; keys may not contain
    // '=' character. Returns 0 if OK, else -1 if a file was not readable.
    function Load(const Filename: string): Integer;

    // When a hash table was loaded from a file by zhash_load, this method will
    // reload the file if it has been modified since, and is "stable", i.e. not
    // still changing. Returns 0 if OK, -1 if there was an error reloading the
    // file.
    function Refresh: Integer;

    // Set hash for automatic value destruction. Note that this assumes that
    // values are NULL-terminated strings. Do not use with different types.
    procedure Autofree;
  end;

  // extended generic type-free hash container
  IZhashx = interface

    // Insert item into hash table with specified key and item.
    // If key is already present returns -1 and leaves existing item unchanged
    // Returns 0 on success.
    function Insert(Key: Pointer; Item: Pointer): Integer;

    // Update or insert item into hash table with specified key and item. If the
    // key is already present, destroys old item and inserts new one. If you set
    // a container item destructor, this is called on the old value. If the key
    // was not already present, inserts a new item. Sets the hash cursor to the
    // new item.
    procedure Update(Key: Pointer; Item: Pointer);

    // Remove an item specified by key from the hash table. If there was no such
    // item, this function does nothing.
    procedure Delete(Key: Pointer);

    // Delete all items from the hash table. If the key destructor is
    // set, calls it on every key. If the item destructor is set, calls
    // it on every item.
    procedure Purge;

    // Return the item at the specified key, or null
    function Lookup(Key: Pointer): Pointer;

    // Reindexes an item from an old key to a new key. If there was no such
    // item, does nothing. Returns 0 if successful, else -1.
    function Rename(OldKey: Pointer; NewKey: Pointer): Integer;

    // Set a free function for the specified hash table item. When the item is
    // destroyed, the free function, if any, is called on that item.
    // Use this when hash items are dynamically allocated, to ensure that
    // you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
    // Returns the item, or NULL if there is no such item.
    function Freefn(Key: Pointer; FreeFn: TZhashxFreeFn): Pointer;

    // Return the number of keys/items in the hash table
    function Size: NativeUInt;

    // Return a zlistx_t containing the keys for the items in the
    // table. Uses the key_duplicator to duplicate all keys and sets the
    // key_destructor as destructor for the list.
    function Keys: IZlistx;

    // Return a zlistx_t containing the values for the items in the
    // table. Uses the duplicator to duplicate all items and sets the
    // destructor as destructor for the list.
    function Values: IZlistx;

    // Simple iterator; returns first item in hash table, in no given order,
    // or NULL if the table is empty. This method is simpler to use than the
    // foreach() method, which is deprecated. To access the key for this item
    // use zhashx_cursor(). NOTE: do NOT modify the table while iterating.
    function First: Pointer;

    // Simple iterator; returns next item in hash table, in no given order,
    // or NULL if the last item was already returned. Use this together with
    // zhashx_first() to process all items in a hash table. If you need the
    // items in sorted order, use zhashx_keys() and then zlistx_sort(). To
    // access the key for this item use zhashx_cursor(). NOTE: do NOT modify
    // the table while iterating.
    function Next: Pointer;

    // After a successful first/next method, returns the key for the item that
    // was returned. This is a constant string that you may not modify or
    // deallocate, and which lasts as long as the item in the hash. After an
    // unsuccessful first/next, returns NULL.
    function Cursor: Pointer;

    // Add a comment to hash table before saving to disk. You can add as many
    // comment lines as you like. These comment lines are discarded when loading
    // the file. If you use a null format, all comments are deleted.
    procedure Comment(const Format: string);

    // Save hash table to a text file in name=value format. Hash values must be
    // printable strings; keys may not contain '=' character. Returns 0 if OK,
    // else -1 if a file error occurred.
    function Save(const Filename: string): Integer;

    // Load hash table from a text file in name=value format; hash table must
    // already exist. Hash values must printable strings; keys may not contain
    // '=' character. Returns 0 if OK, else -1 if a file was not readable.
    function Load(const Filename: string): Integer;

    // When a hash table was loaded from a file by zhashx_load, this method will
    // reload the file if it has been modified since, and is "stable", i.e. not
    // still changing. Returns 0 if OK, -1 if there was an error reloading the
    // file.
    function Refresh: Integer;

    // Serialize hash table to a binary frame that can be sent in a message.
    // The packed format is compatible with the 'dictionary' type defined in
    // http://rfc.zeromq.org/spec:35/FILEMQ, and implemented by zproto:
    //
    //    ; A list of name/value pairs
    //    dictionary      = dict-count *( dict-name dict-value )
    //    dict-count      = number-4
    //    dict-value      = longstr
    //    dict-name       = string
    //
    //    ; Strings are always length + text contents
    //    longstr         = number-4 *VCHAR
    //    string          = number-1 *VCHAR
    //
    //    ; Numbers are unsigned integers in network byte order
    //    number-1        = 1OCTET
    //    number-4        = 4OCTET
    //
    // Comments are not included in the packed data. Item values MUST be
    // strings.
    function Pack: IZframe;

    // Same as pack but uses a user-defined serializer function to convert items
    // into longstr.
    function PackOwn(Serializer: TZhashxSerializerFn): IZframe;

    // Make a copy of the list; items are duplicated if you set a duplicator
    // for the list, otherwise not. Copying a null reference returns a null
    // reference. Note that this method's behavior changed slightly for CZMQ
    // v3.x, as it does not set nor respect autofree. It does however let you
    // duplicate any hash table safely. The old behavior is in zhashx_dup_v2.
    function Dup: IZhashx;

    // Set a user-defined deallocator for hash items; by default items are not
    // freed when the hash is destroyed.
    procedure SetDestructor(&Destructor: TZhashxDestructorFn);

    // Set a user-defined duplicator for hash items; by default items are not
    // copied when the hash is duplicated.
    procedure SetDuplicator(Duplicator: TZhashxDuplicatorFn);

    // Set a user-defined deallocator for keys; by default keys are freed
    // when the hash is destroyed using free().
    procedure SetKeyDestructor(&Destructor: TZhashxDestructorFn);

    // Set a user-defined duplicator for keys; by default keys are duplicated
    // using strdup.
    procedure SetKeyDuplicator(Duplicator: TZhashxDuplicatorFn);

    // Set a user-defined comparator for keys; by default keys are
    // compared using strcmp.
    // The callback function should return zero (0) on matching
    // items.
    procedure SetKeyComparator(Comparator: TZhashxComparatorFn);

    // Set a user-defined hash function for keys; by default keys are
    // hashed by a modified Bernstein hashing function.
    procedure SetKeyHasher(Hasher: TZhashxHashFn);

    // Make copy of hash table; if supplied table is null, returns null.
    // Does not copy items themselves. Rebuilds new table so may be slow on
    // very large tables. NOTE: only works with item values that are strings
    // since there's no other way to know how to duplicate the item value.
    function DupV2: IZhashx;
  end;

  // List of network interfaces available on system
  IZiflist = interface

    // Reload network interfaces from system
    procedure Reload;

    // Return the number of network interfaces on system
    function Size: NativeUInt;

    // Get first network interface, return NULL if there are none
    function First: string;

    // Get next network interface, return NULL if we hit the last one
    function Next: string;

    // Return the current interface IP address as a printable string
    function Address: string;

    // Return the current interface broadcast address as a printable string
    function Broadcast: string;

    // Return the current interface network mask as a printable string
    function Netmask: string;

    // Return the list of interfaces.
    procedure Print;

    // Reload network interfaces from system, including IPv6
    procedure ReloadIpv6;

    // Return true if the current interface uses IPv6
    function IsIpv6: Boolean;
  end;

  // simple generic list container
  IZlist = interface

    // Return the item at the head of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the head item, or NULL if the list is empty.
    function First: Pointer;

    // Return the next item. If the list is empty, returns NULL. To move to
    // the start of the list call zlist_first (). Advances the cursor.
    function Next: Pointer;

    // Return the item at the tail of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the tail item, or NULL if the list is empty.
    function Last: Pointer;

    // Return first item in the list, or null, leaves the cursor
    function Head: Pointer;

    // Return last item in the list, or null, leaves the cursor
    function Tail: Pointer;

    // Return the current item of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the current item, or NULL if the list is empty.
    function Item: Pointer;

    // Append an item to the end of the list, return 0 if OK or -1 if this
    // failed for some reason (out of memory). Note that if a duplicator has
    // been set, this method will also duplicate the item.
    function Append(Item: Pointer): Integer;

    // Push an item to the start of the list, return 0 if OK or -1 if this
    // failed for some reason (out of memory). Note that if a duplicator has
    // been set, this method will also duplicate the item.
    function Push(Item: Pointer): Integer;

    // Pop the item off the start of the list, if any
    function Pop: Pointer;

    // Checks if an item already is present. Uses compare method to determine if
    // items are equal. If the compare method is NULL the check will only compare
    // pointers. Returns true if item is present else false.
    function Exists(Item: Pointer): Boolean;

    // Remove the specified item from the list if present
    procedure Remove(Item: Pointer);

    // Make a copy of list. If the list has autofree set, the copied list will
    // duplicate all items, which must be strings. Otherwise, the list will hold
    // pointers back to the items in the original list. If list is null, returns
    // NULL.
    function Dup: IZlist;

    // Purge all items from list
    procedure Purge;

    // Return number of items in the list
    function Size: NativeUInt;

    // Sort the list. If the compare function is null, sorts the list by
    // ascending key value using a straight ASCII comparison. If you specify
    // a compare function, this decides how items are sorted. The sort is not
    // stable, so may reorder items with the same keys. The algorithm used is
    // combsort, a compromise between performance and simplicity.
    procedure Sort(Compare: TZlistCompareFn);

    // Set list for automatic item destruction; item values MUST be strings.
    // By default a list item refers to a value held elsewhere. When you set
    // this, each time you append or push a list item, zlist will take a copy
    // of the string value. Then, when you destroy the list, it will free all
    // item values automatically. If you use any other technique to allocate
    // list values, you must free them explicitly before destroying the list.
    // The usual technique is to pop list items and destroy them, until the
    // list is empty.
    procedure Autofree;

    // Sets a compare function for this list. The function compares two items.
    // It returns an integer less than, equal to, or greater than zero if the
    // first item is found, respectively, to be less than, to match, or be
    // greater than the second item.
    // This function is used for sorting, removal and exists checking.
    procedure Comparefn(Fn: TZlistCompareFn);

    // Set a free function for the specified list item. When the item is
    // destroyed, the free function, if any, is called on that item.
    // Use this when list items are dynamically allocated, to ensure that
    // you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
    // Returns the item, or NULL if there is no such item.
    function Freefn(Item: Pointer; Fn: TZlistFreeFn; AtTail: Boolean): Pointer;
  end;

  // extended generic list container
  IZlistx = interface

    // Add an item to the head of the list. Calls the item duplicator, if any,
    // on the item. Resets cursor to list head. Returns an item handle on
    // success, NULL if memory was exhausted.
    function AddStart(Item: Pointer): Pointer;

    // Add an item to the tail of the list. Calls the item duplicator, if any,
    // on the item. Resets cursor to list head. Returns an item handle on
    // success, NULL if memory was exhausted.
    function AddEnd(Item: Pointer): Pointer;

    // Return the number of items in the list
    function Size: NativeUInt;

    // Return first item in the list, or null, leaves the cursor
    function Head: Pointer;

    // Return last item in the list, or null, leaves the cursor
    function Tail: Pointer;

    // Return the item at the head of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the head item, or NULL if the list is empty.
    function First: Pointer;

    // Return the next item. At the end of the list (or in an empty list),
    // returns NULL. Use repeated zlistx_next () calls to work through the list
    // from zlistx_first (). First time, acts as zlistx_first().
    function Next: Pointer;

    // Return the previous item. At the start of the list (or in an empty list),
    // returns NULL. Use repeated zlistx_prev () calls to work through the list
    // backwards from zlistx_last (). First time, acts as zlistx_last().
    function Prev: Pointer;

    // Return the item at the tail of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the tail item, or NULL if the list is empty.
    function Last: Pointer;

    // Returns the value of the item at the cursor, or NULL if the cursor is
    // not pointing to an item.
    function Item: Pointer;

    // Returns the handle of the item at the cursor, or NULL if the cursor is
    // not pointing to an item.
    function Cursor: Pointer;

    // Find an item in the list, searching from the start. Uses the item
    // comparator, if any, else compares item values directly. Returns the
    // item handle found, or NULL. Sets the cursor to the found item, if any.
    function Find(Item: Pointer): Pointer;

    // Detach an item from the list, using its handle. The item is not modified,
    // and the caller is responsible for destroying it if necessary. If handle is
    // null, detaches the first item on the list. Returns item that was detached,
    // or null if none was. If cursor was at item, moves cursor to previous item,
    // so you can detach items while iterating forwards through a list.
    function Detach(Handle: Pointer): Pointer;

    // Detach item at the cursor, if any, from the list. The item is not modified,
    // and the caller is responsible for destroying it as necessary. Returns item
    // that was detached, or null if none was. Moves cursor to previous item, so
    // you can detach items while iterating forwards through a list.
    function DetachCur: Pointer;

    // Delete an item, using its handle. Calls the item destructor if any is
    // set. If handle is null, deletes the first item on the list. Returns 0
    // if an item was deleted, -1 if not. If cursor was at item, moves cursor
    // to previous item, so you can delete items while iterating forwards
    // through a list.
    function Delete(Handle: Pointer): Integer;

    // Move an item to the start of the list, via its handle.
    procedure MoveStart(Handle: Pointer);

    // Move an item to the end of the list, via its handle.
    procedure MoveEnd(Handle: Pointer);

    // Remove all items from the list, and destroy them if the item destructor
    // is set.
    procedure Purge;

    // Sort the list. If an item comparator was set, calls that to compare
    // items, otherwise compares on item value. The sort is not stable, so may
    // reorder equal items.
    procedure Sort;

    // Create a new node and insert it into a sorted list. Calls the item
    // duplicator, if any, on the item. If low_value is true, starts searching
    // from the start of the list, otherwise searches from the end. Use the item
    // comparator, if any, to find where to place the new node. Returns a handle
    // to the new node, or NULL if memory was exhausted. Resets the cursor to the
    // list head.
    function Insert(Item: Pointer; LowValue: Boolean): Pointer;

    // Move an item, specified by handle, into position in a sorted list. Uses
    // the item comparator, if any, to determine the new location. If low_value
    // is true, starts searching from the start of the list, otherwise searches
    // from the end.
    procedure Reorder(Handle: Pointer; LowValue: Boolean);

    // Make a copy of the list; items are duplicated if you set a duplicator
    // for the list, otherwise not. Copying a null reference returns a null
    // reference.
    function Dup: IZlistx;

    // Set a user-defined deallocator for list items; by default items are not
    // freed when the list is destroyed.
    procedure SetDestructor(&Destructor: TZlistxDestructorFn);

    // Set a user-defined duplicator for list items; by default items are not
    // copied when the list is duplicated.
    procedure SetDuplicator(Duplicator: TZlistxDuplicatorFn);

    // Set a user-defined comparator for zlistx_find and zlistx_sort; the method
    // must return -1, 0, or 1 depending on whether item1 is less than, equal to,
    // or greater than, item2.
    procedure SetComparator(Comparator: TZlistxComparatorFn);

    // Serialize list to a binary frame that can be sent in a message.
    // The packed format is compatible with the 'strings' type implemented by zproto:
    //
    //    ; A list of strings
    //    list            = list-count *longstr
    //    list-count      = number-4
    //
    //    ; Strings are always length + text contents
    //    longstr         = number-4 *VCHAR
    //
    //    ; Numbers are unsigned integers in network byte order
    //    number-4        = 4OCTET
    function Pack: IZframe;
  end;

  // event-driven reactor
  IZloop = interface

    // Register socket reader with the reactor. When the reader has messages,
    // the reactor will call the handler, passing the arg. Returns 0 if OK, -1
    // if there was an error. If you register the same socket more than once,
    // each instance will invoke its corresponding handler.
    function Reader(const Sock: IZsock; Handler: TZloopReaderFn; Arg: Pointer): Integer;

    // Cancel a socket reader from the reactor. If multiple readers exist for
    // same socket, cancels ALL of them.
    procedure ReaderEnd(const Sock: IZsock);

    // Configure a registered reader to ignore errors. If you do not set this,
    // then readers that have errors are removed from the reactor silently.
    procedure ReaderSetTolerant(const Sock: IZsock);

    // Register low-level libzmq pollitem with the reactor. When the pollitem
    // is ready, will call the handler, passing the arg. Returns 0 if OK, -1
    // if there was an error. If you register the pollitem more than once, each
    // instance will invoke its corresponding handler. A pollitem with
    // socket=NULL and fd=0 means 'poll on FD zero'.
    function Poller(Item: Pointer; Handler: TZloopFn; Arg: Pointer): Integer;

    // Cancel a pollitem from the reactor, specified by socket or FD. If both
    // are specified, uses only socket. If multiple poll items exist for same
    // socket/FD, cancels ALL of them.
    procedure PollerEnd(Item: Pointer);

    // Configure a registered poller to ignore errors. If you do not set this,
    // then poller that have errors are removed from the reactor silently.
    procedure PollerSetTolerant(Item: Pointer);

    // Register a timer that expires after some delay and repeats some number of
    // times. At each expiry, will call the handler, passing the arg. To run a
    // timer forever, use 0 times. Returns a timer_id that is used to cancel the
    // timer in the future. Returns -1 if there was an error.
    function Timer(Delay: NativeUInt; Times: NativeUInt; Handler: TZloopTimerFn; Arg: Pointer): Integer;

    // Cancel a specific timer identified by a specific timer_id (as returned by
    // zloop_timer).
    function TimerEnd(TimerId: Integer): Integer;

    // Register a ticket timer. Ticket timers are very fast in the case where
    // you use a lot of timers (thousands), and frequently remove and add them.
    // The main use case is expiry timers for servers that handle many clients,
    // and which reset the expiry timer for each message received from a client.
    // Whereas normal timers perform poorly as the number of clients grows, the
    // cost of ticket timers is constant, no matter the number of clients. You
    // must set the ticket delay using zloop_set_ticket_delay before creating a
    // ticket. Returns a handle to the timer that you should use in
    // zloop_ticket_reset and zloop_ticket_delete.
    function Ticket(Handler: TZloopTimerFn; Arg: Pointer): Pointer;

    // Reset a ticket timer, which moves it to the end of the ticket list and
    // resets its execution time. This is a very fast operation.
    procedure TicketReset(Handle: Pointer);

    // Delete a ticket timer. We do not actually delete the ticket here, as
    // other code may still refer to the ticket. We mark as deleted, and remove
    // later and safely.
    procedure TicketDelete(Handle: Pointer);

    // Set the ticket delay, which applies to all tickets. If you lower the
    // delay and there are already tickets created, the results are undefined.
    procedure SetTicketDelay(TicketDelay: NativeUInt);

    // Set hard limit on number of timers allowed. Setting more than a small
    // number of timers (10-100) can have a dramatic impact on the performance
    // of the reactor. For high-volume cases, use ticket timers. If the hard
    // limit is reached, the reactor stops creating new timers and logs an
    // error.
    procedure SetMaxTimers(MaxTimers: NativeUInt);

    // Set verbose tracing of reactor on/off. The default verbose setting is
    // off (false).
    procedure SetVerbose(Verbose: Boolean);

    // By default the reactor stops if the process receives a SIGINT or SIGTERM
    // signal. This makes it impossible to shut-down message based architectures
    // like zactors. This method lets you switch off break handling. The default
    // nonstop setting is off (false).
    procedure SetNonstop(Nonstop: Boolean);

    // Start the reactor. Takes control of the thread and returns when the 0MQ
    // context is terminated or the process is interrupted, or any event handler
    // returns -1. Event handlers may register new sockets and timers, and
    // cancel sockets. Returns 0 if interrupted, -1 if canceled by a handler.
    function Start: Integer;
  end;

  // working with multipart messages
  IZmsg = interface

    // Return size of message, i.e. number of frames (0 or more).
    function Size: NativeUInt;

    // Return total size of all frames in message.
    function ContentSize: NativeUInt;

    // Return message routing ID, if the message came from a ZMQ_SERVER socket.
    // Else returns zero.
    function RoutingId: Cardinal;

    // Set routing ID on message. This is used if/when the message is sent to a
    // ZMQ_SERVER socket.
    procedure SetRoutingId(RoutingId: Cardinal);

    // Push frame to the front of the message, i.e. before all other frames.
    // Message takes ownership of frame, will destroy it when message is sent.
    // Returns 0 on success, -1 on error. Deprecates zmsg_push, which did not
    // nullify the caller's frame reference.
    function Prepend(var FrameP: IZframe): Integer;

    // Add frame to the end of the message, i.e. after all other frames.
    // Message takes ownership of frame, will destroy it when message is sent.
    // Returns 0 on success. Deprecates zmsg_add, which did not nullify the
    // caller's frame reference.
    function Append(var FrameP: IZframe): Integer;

    // Remove first frame from message, if any. Returns frame, or NULL.
    function Pop: IZframe;

    // Push block of memory to front of message, as a new frame.
    // Returns 0 on success, -1 on error.
    function Pushmem(Data: PByte; Size: NativeUInt): Integer;

    // Add block of memory to the end of the message, as a new frame.
    // Returns 0 on success, -1 on error.
    function Addmem(Data: PByte; Size: NativeUInt): Integer;

    // Push string as new frame to front of message.
    // Returns 0 on success, -1 on error.
    function Pushstr(const &String: string): Integer;

    // Push string as new frame to end of message.
    // Returns 0 on success, -1 on error.
    function Addstr(const &String: string): Integer;

    // Push formatted string as new frame to front of message.
    // Returns 0 on success, -1 on error.
    function Pushstrf(const Format: string): Integer;

    // Push formatted string as new frame to end of message.
    // Returns 0 on success, -1 on error.
    function Addstrf(const Format: string): Integer;

    // Pop frame off front of message, return as fresh string. If there were
    // no more frames in the message, returns NULL.
    function Popstr: string;

    // Push encoded message as a new frame. Message takes ownership of
    // submessage, so the original is destroyed in this call. Returns 0 on
    // success, -1 on error.
    function Addmsg(var MsgP: IZmsg): Integer;

    // Remove first submessage from message, if any. Returns zmsg_t, or NULL if
    // decoding was not successful.
    function Popmsg: IZmsg;

    // Remove specified frame from list, if present. Does not destroy frame.
    procedure Remove(const Frame: IZframe);

    // Set cursor to first frame in message. Returns frame, or NULL, if the
    // message is empty. Use this to navigate the frames as a list.
    function First: IZframe;

    // Return the next frame. If there are no more frames, returns NULL. To move
    // to the first frame call zmsg_first(). Advances the cursor.
    function Next: IZframe;

    // Return the last frame. If there are no frames, returns NULL.
    function Last: IZframe;

    // Save message to an open file, return 0 if OK, else -1. The message is
    // saved as a series of frames, each with length and data. Note that the
    // file is NOT guaranteed to be portable between operating systems, not
    // versions of CZMQ. The file format is at present undocumented and liable
    // to arbitrary change.
    function Save(&File: Pointer): Integer;

    // Serialize multipart message to a single message frame. Use this method
    // to send structured messages across transports that do not support
    // multipart data. Allocates and returns a new frame containing the
    // serialized message. To decode a serialized message frame, use
    // zmsg_decode ().
    function Encode: IZframe;

    // Create copy of message, as new message object. Returns a fresh zmsg_t
    // object. If message is null, or memory was exhausted, returns null.
    function Dup: IZmsg;

    // Send message to zsys log sink (may be stdout, or system facility as
    // configured by zsys_set_logstream).
    procedure Print;

    // Return true if the two messages have the same number of frames and each
    // frame in the first message is identical to the corresponding frame in the
    // other message. As with zframe_eq, return false if either message is NULL.
    function Eq(const Other: IZmsg): Boolean;

    // Return signal value, 0 or greater, if message is a signal, -1 if not.
    function Signal: Integer;
  end;

  // event-driven reactor
  IZpoller = interface

    // Add a reader to be polled. Returns 0 if OK, -1 on failure. The reader may
    // be a libzmq void * socket, a zsock_t instance, a zactor_t instance or a
    // file handle.
    function Add(const Reader: IZSock): Integer;

    // Remove a reader from the poller; returns 0 if OK, -1 on failure. The reader
    // must have been passed during construction, or in an zpoller_add () call.
    function Remove(Reader: Pointer): Integer;

    // By default the poller stops if the process receives a SIGINT or SIGTERM
    // signal. This makes it impossible to shut-down message based architectures
    // like zactors. This method lets you switch off break handling. The default
    // nonstop setting is off (false).
    procedure SetNonstop(Nonstop: Boolean);

    // Poll the registered readers for I/O, return first reader that has input.
    // The reader will be a libzmq void * socket, a zsock_t, a zactor_t
    // instance or a file handle as specified in zpoller_new/zpoller_add. The
    // timeout should be zero or greater, or -1 to wait indefinitely. Socket
    // priority is defined by their order in the poll list. If you need a
    // balanced poll, use the low level zmq_poll method directly. If the poll
    // call was interrupted (SIGINT), or the ZMQ context was destroyed, or the
    // timeout expired, returns NULL. You can test the actual exit condition by
    // calling zpoller_expired () and zpoller_terminated (). The timeout is in
    // msec.
    function Wait(Timeout: Integer): IZSock;

    // Return true if the last zpoller_wait () call ended because the timeout
    // expired, without any error.
    function Expired: Boolean;

    // Return true if the last zpoller_wait () call ended because the process
    // was interrupted, or the parent context was destroyed.
    function Terminated: Boolean;
  end;

  // high-level socket API that hides libzmq contexts and sockets
  IZsock = interface

    // Bind a socket to a formatted endpoint. For tcp:// endpoints, supports
    // ephemeral ports, if you specify the port number as "*". By default
    // zsock uses the IANA designated range from C000 (49152) to FFFF (65535).
    // To override this range, follow the "*" with "[first-last]". Either or
    // both first and last may be empty. To bind to a random port within the
    // range, use "!" in place of "*".
    //
    // Examples:
    //     tcp://127.0.0.1:*           bind to first free port from C000 up
    //     tcp://127.0.0.1:!           bind to random port from C000 to FFFF
    //     tcp://127.0.0.1:*[60000-]   bind to first free port from 60000 up
    //     tcp://127.0.0.1:![-60000]   bind to random port from C000 to 60000
    //     tcp://127.0.0.1:![55000-55999]
    //                                 bind to random port from 55000 to 55999
    //
    // On success, returns the actual port number used, for tcp:// endpoints,
    // and 0 for other transports. On failure, returns -1. Note that when using
    // ephemeral ports, a port may be reused by different services without
    // clients being aware. Protocols that run on ephemeral ports should take
    // this into account.
    function Bind(const Format: string): Integer;

    // Returns last bound endpoint, if any.
    function Endpoint: string;

    // Unbind a socket from a formatted endpoint.
    // Returns 0 if OK, -1 if the endpoint was invalid or the function
    // isn't supported.
    function Unbind(const Format: string): Integer;

    // Connect a socket to a formatted endpoint
    // Returns 0 if OK, -1 if the endpoint was invalid.
    function Connect(const Format: string): Integer;

    // Disconnect a socket from a formatted endpoint
    // Returns 0 if OK, -1 if the endpoint was invalid or the function
    // isn't supported.
    function Disconnect(const Format: string): Integer;

    // Attach a socket to zero or more endpoints. If endpoints is not null,
    // parses as list of ZeroMQ endpoints, separated by commas, and prefixed by
    // '@' (to bind the socket) or '>' (to connect the socket). Returns 0 if all
    // endpoints were valid, or -1 if there was a syntax error. If the endpoint
    // does not start with '@' or '>', the serverish argument defines whether
    // it is used to bind (serverish = true) or connect (serverish = false).
    function Attach(const Endpoints: string; Serverish: Boolean): Integer;

    // Returns socket type as printable constant string.
    function TypeStr: string;

    // Send a 'picture' message to the socket (or actor). The picture is a
    // string that defines the type of each frame. This makes it easy to send
    // a complex multiframe message in one call. The picture can contain any
    // of these characters, each corresponding to one or two arguments:
    //
    //     i = int (signed)
    //     1 = uint8_t
    //     2 = uint16_t
    //     4 = uint32_t
    //     8 = uint64_t
    //     s = char *
    //     b = byte *, size_t (2 arguments)
    //     c = zchunk_t *
    //     f = zframe_t *
    //     h = zhashx_t *
    //     l = zlistx_t * (DRAFT)
    //     U = zuuid_t *
    //     p = void * (sends the pointer value, only meaningful over inproc)
    //     m = zmsg_t * (sends all frames in the zmsg)
    //     z = sends zero-sized frame (0 arguments)
    //     u = uint (deprecated)
    //
    // Note that s, b, c, and f are encoded the same way and the choice is
    // offered as a convenience to the sender, which may or may not already
    // have data in a zchunk or zframe. Does not change or take ownership of
    // any arguments. Returns 0 if successful, -1 if sending failed for any
    // reason.
    function Send(const Picture: string): Integer;

    // Send a 'picture' message to the socket (or actor). This is a va_list
    // version of zsock_send (), so please consult its documentation for the
    // details.
    function Vsend(const Picture: string; Argptr: va_list): Integer;

    // Receive a 'picture' message to the socket (or actor). See zsock_send for
    // the format and meaning of the picture. Returns the picture elements into
    // a series of pointers as provided by the caller:
    //
    //     i = int * (stores signed integer)
    //     4 = uint32_t * (stores 32-bit unsigned integer)
    //     8 = uint64_t * (stores 64-bit unsigned integer)
    //     s = char ** (allocates new string)
    //     b = byte **, size_t * (2 arguments) (allocates memory)
    //     c = zchunk_t ** (creates zchunk)
    //     f = zframe_t ** (creates zframe)
    //     U = zuuid_t * (creates a zuuid with the data)
    //     h = zhashx_t ** (creates zhashx)
    //     l = zlistx_t ** (creates zlistx) (DRAFT)
    //     p = void ** (stores pointer)
    //     m = zmsg_t ** (creates a zmsg with the remaining frames)
    //     z = null, asserts empty frame (0 arguments)
    //     u = uint * (stores unsigned integer, deprecated)
    //
    // Note that zsock_recv creates the returned objects, and the caller must
    // destroy them when finished with them. The supplied pointers do not need
    // to be initialized. Returns 0 if successful, or -1 if it failed to recv
    // a message, in which case the pointers are not modified. When message
    // frames are truncated (a short message), sets return values to zero/null.
    // If an argument pointer is NULL, does not store any value (skips it).
    // An 'n' picture matches an empty frame; if the message does not match,
    // the method will return -1.
    function Recv(const Picture: string): Integer;

    // Receive a 'picture' message from the socket (or actor). This is a
    // va_list version of zsock_recv (), so please consult its documentation
    // for the details.
    function Vrecv(const Picture: string; Argptr: va_list): Integer;

    // Send a binary encoded 'picture' message to the socket (or actor). This
    // method is similar to zsock_send, except the arguments are encoded in a
    // binary format that is compatible with zproto, and is designed to reduce
    // memory allocations. The pattern argument is a string that defines the
    // type of each argument. Supports these argument types:
    //
    //  pattern    C type                  zproto type:
    //     1       uint8_t                 type = "number" size = "1"
    //     2       uint16_t                type = "number" size = "2"
    //     4       uint32_t                type = "number" size = "3"
    //     8       uint64_t                type = "number" size = "4"
    //     s       char *, 0-255 chars     type = "string"
    //     S       char *, 0-2^32-1 chars  type = "longstr"
    //     c       zchunk_t *              type = "chunk"
    //     f       zframe_t *              type = "frame"
    //     u       zuuid_t *               type = "uuid"
    //     m       zmsg_t *                type = "msg"
    //     p       void *, sends pointer value, only over inproc
    //
    // Does not change or take ownership of any arguments. Returns 0 if
    // successful, -1 if sending failed for any reason.
    function Bsend(const Picture: string): Integer;

    // Receive a binary encoded 'picture' message from the socket (or actor).
    // This method is similar to zsock_recv, except the arguments are encoded
    // in a binary format that is compatible with zproto, and is designed to
    // reduce memory allocations. The pattern argument is a string that defines
    // the type of each argument. See zsock_bsend for the supported argument
    // types. All arguments must be pointers; this call sets them to point to
    // values held on a per-socket basis.
    // For types 1, 2, 4 and 8 the caller must allocate the memory itself before
    // calling zsock_brecv.
    // For types S, the caller must free the value once finished with it, as
    // zsock_brecv will allocate the buffer.
    // For type s, the caller must not free the value as it is stored in a
    // local cache for performance purposes.
    // For types c, f, u and m the caller must call the appropriate destructor
    // depending on the object as zsock_brecv will create new objects.
    // For type p the caller must coordinate with the sender, as it is just a
    // pointer value being passed.
    function Brecv(const Picture: string): Integer;

    // Return socket routing ID if any. This returns 0 if the socket is not
    // of type ZMQ_SERVER or if no request was already received on it.
    function RoutingId: Cardinal;

    // Set routing ID on socket. The socket MUST be of type ZMQ_SERVER.
    // This will be used when sending messages on the socket via the zsock API.
    procedure SetRoutingId(RoutingId: Cardinal);

    // Set socket to use unbounded pipes (HWM=0); use this in cases when you are
    // totally certain the message volume can fit in memory. This method works
    // across all versions of ZeroMQ. Takes a polymorphic socket reference.
    procedure SetUnbounded;

    // Send a signal over a socket. A signal is a short message carrying a
    // success/failure code (by convention, 0 means OK). Signals are encoded
    // to be distinguishable from "normal" messages. Accepts a zsock_t or a
    // zactor_t argument, and returns 0 if successful, -1 if the signal could
    // not be sent. Takes a polymorphic socket reference.
    function Signal(Status: Byte): Integer;

    // Wait on a signal. Use this to coordinate between threads, over pipe
    // pairs. Blocks until the signal is received. Returns -1 on error, 0 or
    // greater on success. Accepts a zsock_t or a zactor_t as argument.
    // Takes a polymorphic socket reference.
    function Wait: Integer;

    // If there is a partial message still waiting on the socket, remove and
    // discard it. This is useful when reading partial messages, to get specific
    // message types.
    procedure Flush;

    // Join a group for the RADIO-DISH pattern. Call only on ZMQ_DISH.
    // Returns 0 if OK, -1 if failed.
    function Join(const Group: string): Integer;

    // Leave a group for the RADIO-DISH pattern. Call only on ZMQ_DISH.
    // Returns 0 if OK, -1 if failed.
    function Leave(const Group: string): Integer;

    // Check whether the socket has available message to read.
    function HasIn: Boolean;

    // Get socket option `router_notify`.
    // Available from libzmq 4.3.0.
    function RouterNotify: Integer;

    // Set socket option `router_notify`.
    // Available from libzmq 4.3.0.
    procedure SetRouterNotify(RouterNotify: Integer);

    // Get socket option `multicast_loop`.
    // Available from libzmq 4.3.0.
    function MulticastLoop: Integer;

    // Set socket option `multicast_loop`.
    // Available from libzmq 4.3.0.
    procedure SetMulticastLoop(MulticastLoop: Integer);

    // Get socket option `metadata`.
    // Available from libzmq 4.3.0.
    function Metadata: string;

    // Set socket option `metadata`.
    // Available from libzmq 4.3.0.
    procedure SetMetadata(const Metadata: string);

    // Get socket option `loopback_fastpath`.
    // Available from libzmq 4.3.0.
    function LoopbackFastpath: Integer;

    // Set socket option `loopback_fastpath`.
    // Available from libzmq 4.3.0.
    procedure SetLoopbackFastpath(LoopbackFastpath: Integer);

    // Get socket option `zap_enforce_domain`.
    // Available from libzmq 4.3.0.
    function ZapEnforceDomain: Integer;

    // Set socket option `zap_enforce_domain`.
    // Available from libzmq 4.3.0.
    procedure SetZapEnforceDomain(ZapEnforceDomain: Integer);

    // Get socket option `gssapi_principal_nametype`.
    // Available from libzmq 4.3.0.
    function GssapiPrincipalNametype: Integer;

    // Set socket option `gssapi_principal_nametype`.
    // Available from libzmq 4.3.0.
    procedure SetGssapiPrincipalNametype(GssapiPrincipalNametype: Integer);

    // Get socket option `gssapi_service_principal_nametype`.
    // Available from libzmq 4.3.0.
    function GssapiServicePrincipalNametype: Integer;

    // Set socket option `gssapi_service_principal_nametype`.
    // Available from libzmq 4.3.0.
    procedure SetGssapiServicePrincipalNametype(GssapiServicePrincipalNametype: Integer);

    // Get socket option `bindtodevice`.
    // Available from libzmq 4.3.0.
    function Bindtodevice: string;

    // Set socket option `bindtodevice`.
    // Available from libzmq 4.3.0.
    procedure SetBindtodevice(const Bindtodevice: string);

    // Get socket option `heartbeat_ivl`.
    // Available from libzmq 4.2.0.
    function HeartbeatIvl: Integer;

    // Set socket option `heartbeat_ivl`.
    // Available from libzmq 4.2.0.
    procedure SetHeartbeatIvl(HeartbeatIvl: Integer);

    // Get socket option `heartbeat_ttl`.
    // Available from libzmq 4.2.0.
    function HeartbeatTtl: Integer;

    // Set socket option `heartbeat_ttl`.
    // Available from libzmq 4.2.0.
    procedure SetHeartbeatTtl(HeartbeatTtl: Integer);

    // Get socket option `heartbeat_timeout`.
    // Available from libzmq 4.2.0.
    function HeartbeatTimeout: Integer;

    // Set socket option `heartbeat_timeout`.
    // Available from libzmq 4.2.0.
    procedure SetHeartbeatTimeout(HeartbeatTimeout: Integer);

    // Get socket option `use_fd`.
    // Available from libzmq 4.2.0.
    function UseFd: Integer;

    // Set socket option `use_fd`.
    // Available from libzmq 4.2.0.
    procedure SetUseFd(UseFd: Integer);

    // Set socket option `xpub_manual`.
    // Available from libzmq 4.2.0.
    procedure SetXpubManual(XpubManual: Integer);

    // Set socket option `xpub_welcome_msg`.
    // Available from libzmq 4.2.0.
    procedure SetXpubWelcomeMsg(const XpubWelcomeMsg: string);

    // Set socket option `stream_notify`.
    // Available from libzmq 4.2.0.
    procedure SetStreamNotify(StreamNotify: Integer);

    // Get socket option `invert_matching`.
    // Available from libzmq 4.2.0.
    function InvertMatching: Integer;

    // Set socket option `invert_matching`.
    // Available from libzmq 4.2.0.
    procedure SetInvertMatching(InvertMatching: Integer);

    // Set socket option `xpub_verboser`.
    // Available from libzmq 4.2.0.
    procedure SetXpubVerboser(XpubVerboser: Integer);

    // Get socket option `connect_timeout`.
    // Available from libzmq 4.2.0.
    function ConnectTimeout: Integer;

    // Set socket option `connect_timeout`.
    // Available from libzmq 4.2.0.
    procedure SetConnectTimeout(ConnectTimeout: Integer);

    // Get socket option `tcp_maxrt`.
    // Available from libzmq 4.2.0.
    function TcpMaxrt: Integer;

    // Set socket option `tcp_maxrt`.
    // Available from libzmq 4.2.0.
    procedure SetTcpMaxrt(TcpMaxrt: Integer);

    // Get socket option `thread_safe`.
    // Available from libzmq 4.2.0.
    function ThreadSafe: Integer;

    // Get socket option `multicast_maxtpdu`.
    // Available from libzmq 4.2.0.
    function MulticastMaxtpdu: Integer;

    // Set socket option `multicast_maxtpdu`.
    // Available from libzmq 4.2.0.
    procedure SetMulticastMaxtpdu(MulticastMaxtpdu: Integer);

    // Get socket option `vmci_buffer_size`.
    // Available from libzmq 4.2.0.
    function VmciBufferSize: Integer;

    // Set socket option `vmci_buffer_size`.
    // Available from libzmq 4.2.0.
    procedure SetVmciBufferSize(VmciBufferSize: Integer);

    // Get socket option `vmci_buffer_min_size`.
    // Available from libzmq 4.2.0.
    function VmciBufferMinSize: Integer;

    // Set socket option `vmci_buffer_min_size`.
    // Available from libzmq 4.2.0.
    procedure SetVmciBufferMinSize(VmciBufferMinSize: Integer);

    // Get socket option `vmci_buffer_max_size`.
    // Available from libzmq 4.2.0.
    function VmciBufferMaxSize: Integer;

    // Set socket option `vmci_buffer_max_size`.
    // Available from libzmq 4.2.0.
    procedure SetVmciBufferMaxSize(VmciBufferMaxSize: Integer);

    // Get socket option `vmci_connect_timeout`.
    // Available from libzmq 4.2.0.
    function VmciConnectTimeout: Integer;

    // Set socket option `vmci_connect_timeout`.
    // Available from libzmq 4.2.0.
    procedure SetVmciConnectTimeout(VmciConnectTimeout: Integer);

    // Get socket option `tos`.
    // Available from libzmq 4.1.0.
    function Tos: Integer;

    // Set socket option `tos`.
    // Available from libzmq 4.1.0.
    procedure SetTos(Tos: Integer);

    // Set socket option `router_handover`.
    // Available from libzmq 4.1.0.
    procedure SetRouterHandover(RouterHandover: Integer);

    // Set socket option `connect_rid`.
    // Available from libzmq 4.1.0.
    procedure SetConnectRid(const ConnectRid: string);

    // Set socket option `connect_rid` from 32-octet binary
    // Available from libzmq 4.1.0.
    procedure SetConnectRidBin(ConnectRid: PByte);

    // Get socket option `handshake_ivl`.
    // Available from libzmq 4.1.0.
    function HandshakeIvl: Integer;

    // Set socket option `handshake_ivl`.
    // Available from libzmq 4.1.0.
    procedure SetHandshakeIvl(HandshakeIvl: Integer);

    // Get socket option `socks_proxy`.
    // Available from libzmq 4.1.0.
    function SocksProxy: string;

    // Set socket option `socks_proxy`.
    // Available from libzmq 4.1.0.
    procedure SetSocksProxy(const SocksProxy: string);

    // Set socket option `xpub_nodrop`.
    // Available from libzmq 4.1.0.
    procedure SetXpubNodrop(XpubNodrop: Integer);

    // Set socket option `router_mandatory`.
    // Available from libzmq 4.0.0.
    procedure SetRouterMandatory(RouterMandatory: Integer);

    // Set socket option `probe_router`.
    // Available from libzmq 4.0.0.
    procedure SetProbeRouter(ProbeRouter: Integer);

    // Set socket option `req_relaxed`.
    // Available from libzmq 4.0.0.
    procedure SetReqRelaxed(ReqRelaxed: Integer);

    // Set socket option `req_correlate`.
    // Available from libzmq 4.0.0.
    procedure SetReqCorrelate(ReqCorrelate: Integer);

    // Set socket option `conflate`.
    // Available from libzmq 4.0.0.
    procedure SetConflate(Conflate: Integer);

    // Get socket option `zap_domain`.
    // Available from libzmq 4.0.0.
    function ZapDomain: string;

    // Set socket option `zap_domain`.
    // Available from libzmq 4.0.0.
    procedure SetZapDomain(const ZapDomain: string);

    // Get socket option `mechanism`.
    // Available from libzmq 4.0.0.
    function Mechanism: Integer;

    // Get socket option `plain_server`.
    // Available from libzmq 4.0.0.
    function PlainServer: Integer;

    // Set socket option `plain_server`.
    // Available from libzmq 4.0.0.
    procedure SetPlainServer(PlainServer: Integer);

    // Get socket option `plain_username`.
    // Available from libzmq 4.0.0.
    function PlainUsername: string;

    // Set socket option `plain_username`.
    // Available from libzmq 4.0.0.
    procedure SetPlainUsername(const PlainUsername: string);

    // Get socket option `plain_password`.
    // Available from libzmq 4.0.0.
    function PlainPassword: string;

    // Set socket option `plain_password`.
    // Available from libzmq 4.0.0.
    procedure SetPlainPassword(const PlainPassword: string);

    // Get socket option `curve_server`.
    // Available from libzmq 4.0.0.
    function CurveServer: Integer;

    // Set socket option `curve_server`.
    // Available from libzmq 4.0.0.
    procedure SetCurveServer(CurveServer: Integer);

    // Get socket option `curve_publickey`.
    // Available from libzmq 4.0.0.
    function CurvePublickey: string;

    // Set socket option `curve_publickey`.
    // Available from libzmq 4.0.0.
    procedure SetCurvePublickey(const CurvePublickey: string);

    // Set socket option `curve_publickey` from 32-octet binary
    // Available from libzmq 4.0.0.
    procedure SetCurvePublickeyBin(CurvePublickey: PByte);

    // Get socket option `curve_secretkey`.
    // Available from libzmq 4.0.0.
    function CurveSecretkey: string;

    // Set socket option `curve_secretkey`.
    // Available from libzmq 4.0.0.
    procedure SetCurveSecretkey(const CurveSecretkey: string);

    // Set socket option `curve_secretkey` from 32-octet binary
    // Available from libzmq 4.0.0.
    procedure SetCurveSecretkeyBin(CurveSecretkey: PByte);

    // Get socket option `curve_serverkey`.
    // Available from libzmq 4.0.0.
    function CurveServerkey: string;

    // Set socket option `curve_serverkey`.
    // Available from libzmq 4.0.0.
    procedure SetCurveServerkey(const CurveServerkey: string);

    // Set socket option `curve_serverkey` from 32-octet binary
    // Available from libzmq 4.0.0.
    procedure SetCurveServerkeyBin(CurveServerkey: PByte);

    // Get socket option `gssapi_server`.
    // Available from libzmq 4.0.0.
    function GssapiServer: Integer;

    // Set socket option `gssapi_server`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiServer(GssapiServer: Integer);

    // Get socket option `gssapi_plaintext`.
    // Available from libzmq 4.0.0.
    function GssapiPlaintext: Integer;

    // Set socket option `gssapi_plaintext`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiPlaintext(GssapiPlaintext: Integer);

    // Get socket option `gssapi_principal`.
    // Available from libzmq 4.0.0.
    function GssapiPrincipal: string;

    // Set socket option `gssapi_principal`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiPrincipal(const GssapiPrincipal: string);

    // Get socket option `gssapi_service_principal`.
    // Available from libzmq 4.0.0.
    function GssapiServicePrincipal: string;

    // Set socket option `gssapi_service_principal`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiServicePrincipal(const GssapiServicePrincipal: string);

    // Get socket option `ipv6`.
    // Available from libzmq 4.0.0.
    function Ipv6: Integer;

    // Set socket option `ipv6`.
    // Available from libzmq 4.0.0.
    procedure SetIpv6(Ipv6: Integer);

    // Get socket option `immediate`.
    // Available from libzmq 4.0.0.
    function Immediate: Integer;

    // Set socket option `immediate`.
    // Available from libzmq 4.0.0.
    procedure SetImmediate(Immediate: Integer);

    // Get socket option `sndhwm`.
    // Available from libzmq 3.0.0.
    function Sndhwm: Integer;

    // Set socket option `sndhwm`.
    // Available from libzmq 3.0.0.
    procedure SetSndhwm(Sndhwm: Integer);

    // Get socket option `rcvhwm`.
    // Available from libzmq 3.0.0.
    function Rcvhwm: Integer;

    // Set socket option `rcvhwm`.
    // Available from libzmq 3.0.0.
    procedure SetRcvhwm(Rcvhwm: Integer);

    // Get socket option `maxmsgsize`.
    // Available from libzmq 3.0.0.
    function Maxmsgsize: Integer;

    // Set socket option `maxmsgsize`.
    // Available from libzmq 3.0.0.
    procedure SetMaxmsgsize(Maxmsgsize: Integer);

    // Get socket option `multicast_hops`.
    // Available from libzmq 3.0.0.
    function MulticastHops: Integer;

    // Set socket option `multicast_hops`.
    // Available from libzmq 3.0.0.
    procedure SetMulticastHops(MulticastHops: Integer);

    // Set socket option `xpub_verbose`.
    // Available from libzmq 3.0.0.
    procedure SetXpubVerbose(XpubVerbose: Integer);

    // Get socket option `tcp_keepalive`.
    // Available from libzmq 3.0.0.
    function TcpKeepalive: Integer;

    // Set socket option `tcp_keepalive`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepalive(TcpKeepalive: Integer);

    // Get socket option `tcp_keepalive_idle`.
    // Available from libzmq 3.0.0.
    function TcpKeepaliveIdle: Integer;

    // Set socket option `tcp_keepalive_idle`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepaliveIdle(TcpKeepaliveIdle: Integer);

    // Get socket option `tcp_keepalive_cnt`.
    // Available from libzmq 3.0.0.
    function TcpKeepaliveCnt: Integer;

    // Set socket option `tcp_keepalive_cnt`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepaliveCnt(TcpKeepaliveCnt: Integer);

    // Get socket option `tcp_keepalive_intvl`.
    // Available from libzmq 3.0.0.
    function TcpKeepaliveIntvl: Integer;

    // Set socket option `tcp_keepalive_intvl`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepaliveIntvl(TcpKeepaliveIntvl: Integer);

    // Get socket option `tcp_accept_filter`.
    // Available from libzmq 3.0.0.
    function TcpAcceptFilter: string;

    // Set socket option `tcp_accept_filter`.
    // Available from libzmq 3.0.0.
    procedure SetTcpAcceptFilter(const TcpAcceptFilter: string);

    // Get socket option `last_endpoint`.
    // Available from libzmq 3.0.0.
    function LastEndpoint: string;

    // Set socket option `router_raw`.
    // Available from libzmq 3.0.0.
    procedure SetRouterRaw(RouterRaw: Integer);

    // Get socket option `ipv4only`.
    // Available from libzmq 3.0.0.
    function Ipv4only: Integer;

    // Set socket option `ipv4only`.
    // Available from libzmq 3.0.0.
    procedure SetIpv4only(Ipv4only: Integer);

    // Set socket option `delay_attach_on_connect`.
    // Available from libzmq 3.0.0.
    procedure SetDelayAttachOnConnect(DelayAttachOnConnect: Integer);

    // Get socket option `hwm`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function Hwm: Integer;

    // Set socket option `hwm`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetHwm(Hwm: Integer);

    // Get socket option `swap`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function Swap: Integer;

    // Set socket option `swap`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetSwap(Swap: Integer);

    // Get socket option `affinity`.
    // Available from libzmq 2.0.0.
    function Affinity: Integer;

    // Set socket option `affinity`.
    // Available from libzmq 2.0.0.
    procedure SetAffinity(Affinity: Integer);

    // Get socket option `identity`.
    // Available from libzmq 2.0.0.
    function Identity: string;

    // Set socket option `identity`.
    // Available from libzmq 2.0.0.
    procedure SetIdentity(const Identity: string);

    // Get socket option `rate`.
    // Available from libzmq 2.0.0.
    function Rate: Integer;

    // Set socket option `rate`.
    // Available from libzmq 2.0.0.
    procedure SetRate(Rate: Integer);

    // Get socket option `recovery_ivl`.
    // Available from libzmq 2.0.0.
    function RecoveryIvl: Integer;

    // Set socket option `recovery_ivl`.
    // Available from libzmq 2.0.0.
    procedure SetRecoveryIvl(RecoveryIvl: Integer);

    // Get socket option `recovery_ivl_msec`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function RecoveryIvlMsec: Integer;

    // Set socket option `recovery_ivl_msec`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetRecoveryIvlMsec(RecoveryIvlMsec: Integer);

    // Get socket option `mcast_loop`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function McastLoop: Integer;

    // Set socket option `mcast_loop`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetMcastLoop(McastLoop: Integer);

    // Get socket option `rcvtimeo`.
    // Available from libzmq 2.2.0.
    function Rcvtimeo: Integer;

    // Set socket option `rcvtimeo`.
    // Available from libzmq 2.2.0.
    procedure SetRcvtimeo(Rcvtimeo: Integer);

    // Get socket option `sndtimeo`.
    // Available from libzmq 2.2.0.
    function Sndtimeo: Integer;

    // Set socket option `sndtimeo`.
    // Available from libzmq 2.2.0.
    procedure SetSndtimeo(Sndtimeo: Integer);

    // Get socket option `sndbuf`.
    // Available from libzmq 2.0.0.
    function Sndbuf: Integer;

    // Set socket option `sndbuf`.
    // Available from libzmq 2.0.0.
    procedure SetSndbuf(Sndbuf: Integer);

    // Get socket option `rcvbuf`.
    // Available from libzmq 2.0.0.
    function Rcvbuf: Integer;

    // Set socket option `rcvbuf`.
    // Available from libzmq 2.0.0.
    procedure SetRcvbuf(Rcvbuf: Integer);

    // Get socket option `linger`.
    // Available from libzmq 2.0.0.
    function Linger: Integer;

    // Set socket option `linger`.
    // Available from libzmq 2.0.0.
    procedure SetLinger(Linger: Integer);

    // Get socket option `reconnect_ivl`.
    // Available from libzmq 2.0.0.
    function ReconnectIvl: Integer;

    // Set socket option `reconnect_ivl`.
    // Available from libzmq 2.0.0.
    procedure SetReconnectIvl(ReconnectIvl: Integer);

    // Get socket option `reconnect_ivl_max`.
    // Available from libzmq 2.0.0.
    function ReconnectIvlMax: Integer;

    // Set socket option `reconnect_ivl_max`.
    // Available from libzmq 2.0.0.
    procedure SetReconnectIvlMax(ReconnectIvlMax: Integer);

    // Get socket option `backlog`.
    // Available from libzmq 2.0.0.
    function Backlog: Integer;

    // Set socket option `backlog`.
    // Available from libzmq 2.0.0.
    procedure SetBacklog(Backlog: Integer);

    // Set socket option `subscribe`.
    // Available from libzmq 2.0.0.
    procedure SetSubscribe(const Subscribe: string);

    // Set socket option `unsubscribe`.
    // Available from libzmq 2.0.0.
    procedure SetUnsubscribe(const Unsubscribe: string);

    // Get socket option `type`.
    // Available from libzmq 2.0.0.
    function &Type: Integer;

    // Get socket option `rcvmore`.
    // Available from libzmq 2.0.0.
    function Rcvmore: Integer;

    // Get socket option `fd`.
    // Available from libzmq 2.0.0.
    function Fd: TSocket;

    // Get socket option `events`.
    // Available from libzmq 2.0.0.
    function Events: Integer;
  end;

  // UUID support class
  IZuuid = interface

    // Set UUID to new supplied ZUUID_LEN-octet value.
    procedure &Set(Source: PByte);

    // Set UUID to new supplied string value skipping '-' and '{' '}'
    // optional delimiters. Return 0 if OK, else returns -1.
    function SetStr(const Source: string): Integer;

    // Return UUID binary data.
    function Data: PByte;

    // Return UUID binary size
    function Size: NativeUInt;

    // Returns UUID as string
    function Str: string;

    // Return UUID in the canonical string format: 8-4-4-4-12, in lower
    // case. Caller does not modify or free returned value. See
    // http://en.wikipedia.org/wiki/Universally_unique_identifier
    function StrCanonical: string;

    // Store UUID blob in target array
    procedure Export(Target: PByte);

    // Check if UUID is same as supplied value
    function Eq(Compare: PByte): Boolean;

    // Check if UUID is different from supplied value
    function Neq(Compare: PByte): Boolean;

    // Make copy of UUID object; if uuid is null, or memory was exhausted,
    // returns null.
    function Dup: IZuuid;
  end;

  // provides a simple actor framework
  TZactor = class(TInterfacedObject, IZactor)
  public
    FOwned: Boolean;
    FHandle: PZactor;
    constructor Create(handle: PZactor; owned: Boolean);
  public

    // Create a new actor passing arbitrary arguments reference.
    constructor New(Task: TZactorFn; Args: Pointer);

    // Destroy an actor.
    destructor Destroy; override;

    // Probe the supplied object, and report if it looks like a zactor_t.
    class function &Is(This: Pointer): Boolean;

    // Probe the supplied reference. If it looks like a zactor_t instance,
    // return the underlying libzmq actor handle; else if it looks like
    // a libzmq actor handle, return the supplied value.
    class function Resolve(This: Pointer): Pointer;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZactor; owned: Boolean): IZactor;
    class function UnWrap(const Value: IZactor): PZactor;
  protected

    // Send a zmsg message to the actor, take ownership of the message
    // and destroy when it has been sent.
    function Send(var MsgP: IZmsg): Integer;

    // Receive a zmsg message from the actor. Returns NULL if the actor
    // was interrupted before the message could be received, or if there
    // was a timeout on the actor.
    function Recv: IZmsg;

    // Return the actor's zsock handle. Use this when you absolutely need
    // to work with the zsock instance rather than the actor.
    function Sock: IZsock;

    // Change default destructor by custom function. Actor MUST be able to handle new message instead of default $TERM.
    procedure SetDestructor(&Destructor: TZactorDestructorFn);
  end;

  // armoured text encoding and decoding
  TZarmour = class(TInterfacedObject, IZarmour)
  public
    FOwned: Boolean;
    FHandle: PZarmour;
    constructor Create(handle: PZarmour; owned: Boolean);
  public

    // Create a new zarmour
    constructor New;

    // Destroy the zarmour
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZarmour; owned: Boolean): IZarmour;
    class function UnWrap(const Value: IZarmour): PZarmour;
  protected

    // Encode a stream of bytes into an armoured string. Returns the armoured
    // string, or NULL if there was insufficient memory available to allocate
    // a new string.
    function Encode(Data: PByte; Size: NativeUInt): string;

    // Decode an armoured string into a chunk. The decoded output is
    // null-terminated, so it may be treated as a string, if that's what
    // it was prior to encoding.
    function Decode(const Data: string): IZchunk;

    // Get the mode property.
    function Mode: Integer;

    // Get printable string for mode.
    function ModeStr: string;

    // Set the mode property.
    procedure SetMode(Mode: Integer);

    // Return true if padding is turned on.
    function Pad: Boolean;

    // Turn padding on or off. Default is on.
    procedure SetPad(Pad: Boolean);

    // Get the padding character.
    function PadChar: AnsiChar;

    // Set the padding character.
    procedure SetPadChar(PadChar: AnsiChar);

    // Return if splitting output into lines is turned on. Default is off.
    function LineBreaks: Boolean;

    // Turn splitting output into lines on or off.
    procedure SetLineBreaks(LineBreaks: Boolean);

    // Get the line length used for splitting lines.
    function LineLength: NativeUInt;

    // Set the line length used for splitting lines.
    procedure SetLineLength(LineLength: NativeUInt);

    // Print properties of object
    procedure Print;
  end;

  // work with CURVE security certificates
  TZcert = class(TInterfacedObject, IZcert)
  public
    FOwned: Boolean;
    FHandle: PZcert;
    constructor Create(handle: PZcert; owned: Boolean);
  public

    // Create and initialize a new certificate in memory
    constructor New;

    // Accepts public/secret key pair from caller
    constructor NewFrom(PublicKey: PByte; SecretKey: PByte);

    // Accepts public/secret key text pair from caller
    constructor NewFromTxt(const PublicTxt: string; const SecretTxt: string);

    // Load certificate from file
    constructor Load(const Filename: string);

    // Destroy a certificate in memory
    destructor Destroy; override;

    // Self test of this class
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZcert; owned: Boolean): IZcert;
    class function UnWrap(const Value: IZcert): PZcert;
  protected

    // Return public part of key pair as 32-byte binary string
    function PublicKey: PByte;

    // Return secret part of key pair as 32-byte binary string
    function SecretKey: PByte;

    // Return public part of key pair as Z85 armored string
    function PublicTxt: string;

    // Return secret part of key pair as Z85 armored string
    function SecretTxt: string;

    // Set certificate metadata from formatted string.
    procedure SetMeta(const Name: string; const Format: string);

    // Unset certificate metadata.
    procedure UnsetMeta(const Name: string);

    // Get metadata value from certificate; if the metadata value doesn't
    // exist, returns NULL.
    function Meta(const Name: string): string;

    // Get list of metadata fields from certificate. Caller is responsible for
    // destroying list. Caller should not modify the values of list items.
    function MetaKeys: IZlist;

    // Save full certificate (public + secret) to file for persistent storage
    // This creates one public file and one secret file (filename + "_secret").
    function Save(const Filename: string): Integer;

    // Save public certificate only to file for persistent storage
    function SavePublic(const Filename: string): Integer;

    // Save secret certificate only to file for persistent storage
    function SaveSecret(const Filename: string): Integer;

    // Apply certificate to socket, i.e. use for CURVE security on socket.
    // If certificate was loaded from public file, the secret key will be
    // undefined, and this certificate will not work successfully.
    procedure Apply(const Socket: IZSock);

    // Return copy of certificate; if certificate is NULL or we exhausted
    // heap memory, returns NULL.
    function Dup: IZcert;

    // Return true if two certificates have the same keys
    function Eq(const Compare: IZcert): Boolean;

    // Print certificate contents to stdout
    procedure Print;
  end;

  // work with CURVE security certificate stores
  TZcertstore = class(TInterfacedObject, IZcertstore)
  public
    FOwned: Boolean;
    FHandle: PZcertstore;
    constructor Create(handle: PZcertstore; owned: Boolean);
  public

    // Create a new certificate store from a disk directory, loading and
    // indexing all certificates in that location. The directory itself may be
    // absent, and created later, or modified at any time. The certificate store
    // is automatically refreshed on any zcertstore_lookup() call. If the
    // location is specified as NULL, creates a pure-memory store, which you
    // can work with by inserting certificates at runtime.
    constructor New(const Location: string);

    // Destroy a certificate store object in memory. Does not affect anything
    // stored on disk.
    destructor Destroy; override;

    // Self test of this class
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZcertstore; owned: Boolean): IZcertstore;
    class function UnWrap(const Value: IZcertstore): PZcertstore;
  protected

    // Override the default disk loader with a custom loader fn.
    procedure SetLoader(Loader: TZcertstoreLoader; &Destructor: TZcertstoreDestructor; State: PByte);

    // Look up certificate by public key, returns zcert_t object if found,
    // else returns NULL. The public key is provided in Z85 text format.
    function Lookup(const PublicKey: string): IZcert;

    // Insert certificate into certificate store in memory. Note that this
    // does not save the certificate to disk. To do that, use zcert_save()
    // directly on the certificate. Takes ownership of zcert_t object.
    procedure Insert(var CertP: IZcert);

    // Empty certificate hashtable. This wrapper exists to be friendly to bindings,
    // which don't usually have access to struct internals.
    procedure Empty;

    // Print list of certificates in store to logging facility
    procedure Print;

    // Return a list of all the certificates in the store.
    // The caller takes ownership of the zlistx_t object and is responsible
    // for destroying it.  The caller does not take ownership of the zcert_t
    // objects.
    function Certs: IZlistx;
  end;

  // work with memory chunks
  TZchunk = class(TInterfacedObject, IZchunk)
  public
    FOwned: Boolean;
    FHandle: PZchunk;
    constructor Create(handle: PZchunk; owned: Boolean);
  public

    // Create a new chunk of the specified size. If you specify the data, it
    // is copied into the chunk. If you do not specify the data, the chunk is
    // allocated and left empty, and you can then add data using zchunk_append.
    constructor New(Data: PByte; Size: NativeUInt);

    // Create a new chunk from memory. Take ownership of the memory and calling the destructor
    // on destroy.
    constructor Frommem(Data: PByte; Size: NativeUInt; &Destructor: TZchunkDestructorFn; Hint: Pointer);

    // Destroy a chunk
    destructor Destroy; override;

    // Read chunk from an open file descriptor
    class function Read(Handle: Pointer; Bytes: NativeUInt): IZchunk;

    // Try to slurp an entire file into a chunk. Will read up to maxsize of
    // the file. If maxsize is 0, will attempt to read the entire file and
    // fail with an assertion if that cannot fit into memory. Returns a new
    // chunk containing the file data, or NULL if the file could not be read.
    class function Slurp(const Filename: string; Maxsize: NativeUInt): IZchunk;

    // Transform zchunk into a zframe that can be sent in a message.
    // Take ownership of the chunk.
    class function Packx(var SelfP: IZchunk): IZframe;

    // Transform a zframe into a zchunk.
    class function Unpack(const Frame: IZframe): IZchunk;

    // Probe the supplied object, and report if it looks like a zchunk_t.
    class function &Is(This: Pointer): Boolean;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZchunk; owned: Boolean): IZchunk;
    class function UnWrap(const Value: IZchunk): PZchunk;
  protected

    // Resizes chunk max_size as requested; chunk_cur size is set to zero
    procedure Resize(Size: NativeUInt);

    // Return chunk cur size
    function Size: NativeUInt;

    // Return chunk max size
    function MaxSize: NativeUInt;

    // Return chunk data
    function Data: PByte;

    // Set chunk data from user-supplied data; truncate if too large. Data may
    // be null. Returns actual size of chunk
    function &Set(Data: PByte; Size: NativeUInt): NativeUInt;

    // Fill chunk data from user-supplied octet
    function Fill(Filler: Byte; Size: NativeUInt): NativeUInt;

    // Append user-supplied data to chunk, return resulting chunk size. If the
    // data would exceeded the available space, it is truncated. If you want to
    // grow the chunk to accommodate new data, use the zchunk_extend method.
    function Append(Data: PByte; Size: NativeUInt): NativeUInt;

    // Append user-supplied data to chunk, return resulting chunk size. If the
    // data would exceeded the available space, the chunk grows in size.
    function Extend(Data: PByte; Size: NativeUInt): NativeUInt;

    // Copy as much data from 'source' into the chunk as possible; returns the
    // new size of chunk. If all data from 'source' is used, returns exhausted
    // on the source chunk. Source can be consumed as many times as needed until
    // it is exhausted. If source was already exhausted, does not change chunk.
    function Consume(const Source: IZchunk): NativeUInt;

    // Returns true if the chunk was exhausted by consume methods, or if the
    // chunk has a size of zero.
    function Exhausted: Boolean;

    // Write chunk to an open file descriptor
    function Write(Handle: Pointer): Integer;

    // Create copy of chunk, as new chunk object. Returns a fresh zchunk_t
    // object, or null if there was not enough heap memory. If chunk is null,
    // returns null.
    function Dup: IZchunk;

    // Return chunk data encoded as printable hex string. Caller must free
    // string when finished with it.
    function Strhex: string;

    // Return chunk data copied into freshly allocated string
    // Caller must free string when finished with it.
    function Strdup: string;

    // Return TRUE if chunk body is equal to string, excluding terminator
    function Streq(const &String: string): Boolean;

    // Transform zchunk into a zframe that can be sent in a message.
    function Pack: IZframe;

    // Calculate SHA1 digest for chunk, using zdigest class.
    function Digest: string;

    // Dump chunk to FILE stream, for debugging and tracing.
    procedure Fprint(&File: Pointer);

    // Dump message to stderr, for debugging and tracing.
    // See zchunk_fprint for details
    procedure Print;
  end;

  // millisecond clocks and delays
  TZclock = class
  public

    // Sleep for a number of milliseconds
    class procedure Sleep(Msecs: Integer);

    // Return current system clock as milliseconds. Note that this clock can
    // jump backwards (if the system clock is changed) so is unsafe to use for
    // timers and time offsets. Use zclock_mono for that instead.
    class function Time: Int64;

    // Return current monotonic clock in milliseconds. Use this when you compute
    // time offsets. The monotonic clock is not affected by system changes and
    // so will never be reset backwards, unlike a system clock.
    class function Mono: Int64;

    // Return current monotonic clock in microseconds. Use this when you compute
    // time offsets. The monotonic clock is not affected by system changes and
    // so will never be reset backwards, unlike a system clock.
    class function Usecs: Int64;

    // Return formatted date/time as fresh string. Free using zstr_free().
    class function Timestr: string;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  // work with config files written in rfc.zeromq.org/spec:4/ZPL.
  TZconfig = class(TInterfacedObject, IZconfig)
  public
    FOwned: Boolean;
    FHandle: PZconfig;
    constructor Create(handle: PZconfig; owned: Boolean);
  public

    // Create new config item
    constructor New(const Name: string; const Parent: IZconfig);

    // Load a config tree from a specified ZPL text file; returns a zconfig_t
    // reference for the root, if the file exists and is readable. Returns NULL
    // if the file does not exist.
    constructor Load(const Filename: string);

    // Equivalent to zconfig_load, taking a format string instead of a fixed
    // filename.
    constructor Loadf(const Format: string);

    // Destroy a config item and all its children
    destructor Destroy; override;

    // Reload config tree from same file that it was previously loaded from.
    // Returns 0 if OK, -1 if there was an error (and then does not change
    // existing data).
    class function Reload(var SelfP: IZconfig): Integer;

    // Load a config tree from a memory chunk
    class function ChunkLoad(const Chunk: IZchunk): IZconfig;

    // Load a config tree from a null-terminated string
    class function StrLoad(const &String: string): IZconfig;

    // Destroy node and subtree (all children)
    class procedure Remove(var SelfP: IZconfig);

    // Self test of this class
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZconfig; owned: Boolean): IZconfig;
    class function UnWrap(const Value: IZconfig): PZconfig;
  protected

    // Create copy of zconfig, caller MUST free the value
    // Create copy of config, as new zconfig object. Returns a fresh zconfig_t
    // object. If config is null, or memory was exhausted, returns null.
    function Dup: IZconfig;

    // Return name of config item
    function Name: string;

    // Return value of config item
    function Value: string;

    // Insert or update configuration key with value
    procedure Put(const Path: string; const Value: string);

    // Equivalent to zconfig_put, accepting a format specifier and variable
    // argument list, instead of a single string value.
    procedure Putf(const Path: string; const Format: string);

    // Get value for config item into a string value; leading slash is optional
    // and ignored.
    function Get(const Path: string; const DefaultValue: string): string;

    // Set config item name, name may be NULL
    procedure SetName(const Name: string);

    // Set new value for config item. The new value may be a string, a printf
    // format, or NULL. Note that if string may possibly contain '%', or if it
    // comes from an insecure source, you must use '%s' as the format, followed
    // by the string.
    procedure SetValue(const Format: string);

    // Find our first child, if any
    function Child: IZconfig;

    // Find our first sibling, if any
    function Next: IZconfig;

    // Find a config item along a path; leading slash is optional and ignored.
    function Locate(const Path: string): IZconfig;

    // Locate the last config item at a specified depth
    function AtDepth(Level: Integer): IZconfig;

    // Execute a callback for each config item in the tree; returns zero if
    // successful, else -1.
    function Execute(Handler: TZconfigFct; Arg: Pointer): Integer;

    // Add comment to config item before saving to disk. You can add as many
    // comment lines as you like. If you use a null format, all comments are
    // deleted.
    procedure SetComment(const Format: string);

    // Return comments of config item, as zlist.
    function Comments: IZlist;

    // Save a config tree to a specified ZPL text file, where a filename
    // "-" means dump to standard output.
    function Save(const Filename: string): Integer;

    // Equivalent to zconfig_save, taking a format string instead of a fixed
    // filename.
    function Savef(const Format: string): Integer;

    // Report filename used during zconfig_load, or NULL if none
    function Filename: string;

    // Save a config tree to a new memory chunk
    function ChunkSave: IZchunk;

    // Save a config tree to a new null terminated string
    function StrSave: string;

    // Return true if a configuration tree was loaded from a file and that
    // file has changed in since the tree was loaded.
    function HasChanged: Boolean;

    // Destroy subtree (all children)
    procedure RemoveSubtree;

    // Print the config file to open stream
    procedure Fprint(&File: Pointer);

    // Print properties of object
    procedure Print;
  end;

  // provides hashing functions (SHA-1 at present)
  TZdigest = class(TInterfacedObject, IZdigest)
  public
    FOwned: Boolean;
    FHandle: PZdigest;
    constructor Create(handle: PZdigest; owned: Boolean);
  public

    // Constructor - creates new digest object, which you use to build up a
    // digest by repeatedly calling zdigest_update() on chunks of data.
    constructor New;

    // Destroy a digest object
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZdigest; owned: Boolean): IZdigest;
    class function UnWrap(const Value: IZdigest): PZdigest;
  protected

    // Add buffer into digest calculation
    procedure Update(Buffer: PByte; Length: NativeUInt);

    // Return final digest hash data. If built without crypto support,
    // returns NULL.
    function Data: PByte;

    // Return final digest hash size
    function Size: NativeUInt;

    // Return digest as printable hex string; caller should not modify nor
    // free this string. After calling this, you may not use zdigest_update()
    // on the same digest. If built without crypto support, returns NULL.
    function &String: string;
  end;

  // work with file-system directories
  TZdir = class(TInterfacedObject, IZdir)
  public
    FOwned: Boolean;
    FHandle: PZdir;
    constructor Create(handle: PZdir; owned: Boolean);
  public

    // Create a new directory item that loads in the full tree of the specified
    // path, optionally located under some parent path. If parent is "-", then
    // loads only the top-level directory, and does not use parent as a path.
    constructor New(const Path: string; const Parent: string);

    // Destroy a directory tree and all children it contains.
    destructor Destroy; override;

    // Calculate differences between two versions of a directory tree.
    // Returns a list of zdir_patch_t patches. Either older or newer may
    // be null, indicating the directory is empty/absent. If alias is set,
    // generates virtual filename (minus path, plus alias).
    class function Diff(const Older: IZdir; const Newer: IZdir; const Alias: string): IZlist;

    // Create a new zdir_watch actor instance:
    //
    //     zactor_t *watch = zactor_new (zdir_watch, NULL);
    //
    // Destroy zdir_watch instance:
    //
    //     zactor_destroy (&watch);
    //
    // Enable verbose logging of commands and activity:
    //
    //     zstr_send (watch, "VERBOSE");
    //
    // Subscribe to changes to a directory path:
    //
    //     zsock_send (watch, "ss", "SUBSCRIBE", "directory_path");
    //
    // Unsubscribe from changes to a directory path:
    //
    //     zsock_send (watch, "ss", "UNSUBSCRIBE", "directory_path");
    //
    // Receive directory changes:
    //     zsock_recv (watch, "sp", &path, &patches);
    //
    //     // Delete the received data.
    //     free (path);
    //     zlist_destroy (&patches);
    class procedure Watch(const Pipe: IZsock; Unused: Pointer);

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZdir; owned: Boolean): IZdir;
    class function UnWrap(const Value: IZdir): PZdir;
  protected

    // Return directory path
    function Path: string;

    // Return last modification time for directory.
    function Modified: Int64;

    // Return total hierarchy size, in bytes of data contained in all files
    // in the directory tree.
    function Cursize: Longint;

    // Return directory count
    function Count: NativeUInt;

    // Returns a sorted list of zfile objects; Each entry in the list is a pointer
    // to a zfile_t item already allocated in the zdir tree. Do not destroy the
    // original zdir tree until you are done with this list.
    function List: IZlist;

    // Remove directory, optionally including all files that it contains, at
    // all levels. If force is false, will only remove the directory if empty.
    // If force is true, will remove all files and all subdirectories.
    procedure Remove(Force: Boolean);

    // Return full contents of directory as a zdir_patch list.
    function Resync(const Alias: string): IZlist;

    // Load directory cache; returns a hash table containing the SHA-1 digests
    // of every file in the tree. The cache is saved between runs in .cache.
    function Cache: IZhash;

    // Print contents of directory to open stream
    procedure Fprint(&File: Pointer; Indent: Integer);

    // Print contents of directory to stdout
    procedure Print(Indent: Integer);
  end;

  // work with directory patches
  TZdirPatch = class(TInterfacedObject, IZdirPatch)
  public
    FOwned: Boolean;
    FHandle: PZdirPatch;
    constructor Create(handle: PZdirPatch; owned: Boolean);
  public

    // Create new patch
    constructor New(const Path: string; const &File: IZfile; Op: Integer; const Alias: string);

    // Destroy a patch
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZdirPatch; owned: Boolean): IZdirPatch;
    class function UnWrap(const Value: IZdirPatch): PZdirPatch;
  protected

    // Create copy of a patch. If the patch is null, or memory was exhausted,
    // returns null.
    function Dup: IZdirPatch;

    // Return patch file directory path
    function Path: string;

    // Return patch file item
    function &File: IZfile;

    // Return operation
    function Op: Integer;

    // Return patch virtual file path
    function Vpath: string;

    // Calculate hash digest for file (create only)
    procedure DigestSet;

    // Return hash digest for patch file
    function Digest: string;
  end;

  // helper functions for working with files.
  TZfile = class(TInterfacedObject, IZfile)
  public
    FOwned: Boolean;
    FHandle: PZfile;
    constructor Create(handle: PZfile; owned: Boolean);
  public

    // If file exists, populates properties. CZMQ supports portable symbolic
    // links, which are files with the extension ".ln". A symbolic link is a
    // text file containing one line, the filename of a target file. Reading
    // data from the symbolic link actually reads from the target file. Path
    // may be NULL, in which case it is not used.
    constructor New(const Path: string; const Name: string);

    // Create new temporary file for writing via tmpfile. File is automatically
    // deleted on destroy
    constructor Tmp;

    // Destroy a file item
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZfile; owned: Boolean): IZfile;
    class function UnWrap(const Value: IZfile): PZfile;
  protected

    // Duplicate a file item, returns a newly constructed item. If the file
    // is null, or memory was exhausted, returns null.
    function Dup: IZfile;

    // Return file name, remove path if provided
    function Filename(const Path: string): string;

    // Refresh file properties from disk; this is not done automatically
    // on access methods, otherwise it is not possible to compare directory
    // snapshots.
    procedure Restat;

    // Return when the file was last modified. If you want this to reflect the
    // current situation, call zfile_restat before checking this property.
    function Modified: Int64;

    // Return the last-known size of the file. If you want this to reflect the
    // current situation, call zfile_restat before checking this property.
    function Cursize: Longint;

    // Return true if the file is a directory. If you want this to reflect
    // any external changes, call zfile_restat before checking this property.
    function IsDirectory: Boolean;

    // Return true if the file is a regular file. If you want this to reflect
    // any external changes, call zfile_restat before checking this property.
    function IsRegular: Boolean;

    // Return true if the file is readable by this process. If you want this to
    // reflect any external changes, call zfile_restat before checking this
    // property.
    function IsReadable: Boolean;

    // Return true if the file is writeable by this process. If you want this
    // to reflect any external changes, call zfile_restat before checking this
    // property.
    function IsWriteable: Boolean;

    // Check if file has stopped changing and can be safely processed.
    // Updates the file statistics from disk at every call.
    function IsStable: Boolean;

    // Return true if the file was changed on disk since the zfile_t object
    // was created, or the last zfile_restat() call made on it.
    function HasChanged: Boolean;

    // Remove the file from disk
    procedure Remove;

    // Open file for reading
    // Returns 0 if OK, -1 if not found or not accessible
    function Input: Integer;

    // Open file for writing, creating directory if needed
    // File is created if necessary; chunks can be written to file at any
    // location. Returns 0 if OK, -1 if error.
    function Output: Integer;

    // Read chunk from file at specified position. If this was the last chunk,
    // sets the eof property. Returns a null chunk in case of error.
    function Read(Bytes: NativeUInt; Offset: Longint): IZchunk;

    // Returns true if zfile_read() just read the last chunk in the file.
    function Eof: Boolean;

    // Write chunk to file at specified position
    // Return 0 if OK, else -1
    function Write(const Chunk: IZchunk; Offset: Longint): Integer;

    // Read next line of text from file. Returns a pointer to the text line,
    // or NULL if there was nothing more to read from the file.
    function Readln: string;

    // Close file, if open
    procedure Close;

    // Return file handle, if opened
    function Handle: Pointer;

    // Calculate SHA1 digest for file, using zdigest class.
    function Digest: string;
  end;

  // working with single message frames
  TZframe = class(TInterfacedObject, IZframe)
  public
    FOwned: Boolean;
    FHandle: PZframe;
    constructor Create(handle: PZframe; owned: Boolean);
  public

    // Create a new frame. If size is not null, allocates the frame data
    // to the specified size. If additionally, data is not null, copies
    // size octets from the specified data into the frame body.
    constructor New(Data: PByte; Size: NativeUInt);

    // Create an empty (zero-sized) frame
    constructor NewEmpty;

    // Create a frame with a specified string content.
    constructor From(const &String: string);

    // Create a new frame from memory. Take ownership of the memory and calling the destructor
    // on destroy.
    constructor Frommem(Data: PByte; Size: NativeUInt; &Destructor: TZframeDestructorFn; Hint: Pointer);

    // Receive frame from socket, returns zframe_t object or NULL if the recv
    // was interrupted. Does a blocking recv, if you want to not block then use
    // zpoller or zloop.
    constructor Recv(const Source: IZSock);

    // Destroy a frame
    destructor Destroy; override;

    // Send a frame to a socket, destroy frame after sending.
    // Return -1 on error, 0 on success.
    class function Send(var SelfP: IZframe; const Dest: IZSock; Flags: Integer): Integer;

    // Probe the supplied object, and report if it looks like a zframe_t.
    class function &Is(This: Pointer): Boolean;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZframe; owned: Boolean): IZframe;
    class function UnWrap(const Value: IZframe): PZframe;
  protected

    // Return number of bytes in frame data
    function Size: NativeUInt;

    // Return address of frame data
    function Data: PByte;

    // Return meta data property for frame
    // The caller shall not modify or free the returned value, which shall be
    // owned by the message.
    function Meta(const &Property: string): string;

    // Create a new frame that duplicates an existing frame. If frame is null,
    // or memory was exhausted, returns null.
    function Dup: IZframe;

    // Return frame data encoded as printable hex string, useful for 0MQ UUIDs.
    // Caller must free string when finished with it.
    function Strhex: string;

    // Return frame data copied into freshly allocated string
    // Caller must free string when finished with it.
    function Strdup: string;

    // Return TRUE if frame body is equal to string, excluding terminator
    function Streq(const &String: string): Boolean;

    // Return frame MORE indicator (1 or 0), set when reading frame from socket
    // or by the zframe_set_more() method
    function More: Integer;

    // Set frame MORE indicator (1 or 0). Note this is NOT used when sending
    // frame to socket, you have to specify flag explicitly.
    procedure SetMore(More: Integer);

    // Return frame routing ID, if the frame came from a ZMQ_SERVER socket.
    // Else returns zero.
    function RoutingId: Cardinal;

    // Set routing ID on frame. This is used if/when the frame is sent to a
    // ZMQ_SERVER socket.
    procedure SetRoutingId(RoutingId: Cardinal);

    // Return frame group of radio-dish pattern.
    function Group: string;

    // Set group on frame. This is used if/when the frame is sent to a
    // ZMQ_RADIO socket.
    // Return -1 on error, 0 on success.
    function SetGroup(const Group: string): Integer;

    // Return TRUE if two frames have identical size and data
    // If either frame is NULL, equality is always false.
    function Eq(const Other: IZframe): Boolean;

    // Set new contents for frame
    procedure Reset(Data: PByte; Size: NativeUInt);

    // Send message to zsys log sink (may be stdout, or system facility as
    // configured by zsys_set_logstream). Prefix shows before frame, if not null.
    procedure Print(const Prefix: string);
  end;

  // generic type-free hash container (simple)
  TZhash = class(TInterfacedObject, IZhash)
  public
    FOwned: Boolean;
    FHandle: PZhash;
    constructor Create(handle: PZhash; owned: Boolean);
  public

    // Create a new, empty hash container
    constructor New;

    // Unpack binary frame into a new hash table. Packed data must follow format
    // defined by zhash_pack. Hash table is set to autofree. An empty frame
    // unpacks to an empty hash table.
    constructor Unpack(const Frame: IZframe);

    // Destroy a hash container and all items in it
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZhash; owned: Boolean): IZhash;
    class function UnWrap(const Value: IZhash): PZhash;
  protected

    // Insert item into hash table with specified key and item.
    // If key is already present returns -1 and leaves existing item unchanged
    // Returns 0 on success.
    function Insert(const Key: string; Item: Pointer): Integer;

    // Update item into hash table with specified key and item.
    // If key is already present, destroys old item and inserts new one.
    // Use free_fn method to ensure deallocator is properly called on item.
    procedure Update(const Key: string; Item: Pointer);

    // Remove an item specified by key from the hash table. If there was no such
    // item, this function does nothing.
    procedure Delete(const Key: string);

    // Return the item at the specified key, or null
    function Lookup(const Key: string): Pointer;

    // Reindexes an item from an old key to a new key. If there was no such
    // item, does nothing. Returns 0 if successful, else -1.
    function Rename(const OldKey: string; const NewKey: string): Integer;

    // Set a free function for the specified hash table item. When the item is
    // destroyed, the free function, if any, is called on that item.
    // Use this when hash items are dynamically allocated, to ensure that
    // you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
    // Returns the item, or NULL if there is no such item.
    function Freefn(const Key: string; FreeFn: TZhashFreeFn): Pointer;

    // Return the number of keys/items in the hash table
    function Size: NativeUInt;

    // Make copy of hash table; if supplied table is null, returns null.
    // Does not copy items themselves. Rebuilds new table so may be slow on
    // very large tables. NOTE: only works with item values that are strings
    // since there's no other way to know how to duplicate the item value.
    function Dup: IZhash;

    // Return keys for items in table
    function Keys: IZlist;

    // Simple iterator; returns first item in hash table, in no given order,
    // or NULL if the table is empty. This method is simpler to use than the
    // foreach() method, which is deprecated. To access the key for this item
    // use zhash_cursor(). NOTE: do NOT modify the table while iterating.
    function First: Pointer;

    // Simple iterator; returns next item in hash table, in no given order,
    // or NULL if the last item was already returned. Use this together with
    // zhash_first() to process all items in a hash table. If you need the
    // items in sorted order, use zhash_keys() and then zlist_sort(). To
    // access the key for this item use zhash_cursor(). NOTE: do NOT modify
    // the table while iterating.
    function Next: Pointer;

    // After a successful first/next method, returns the key for the item that
    // was returned. This is a constant string that you may not modify or
    // deallocate, and which lasts as long as the item in the hash. After an
    // unsuccessful first/next, returns NULL.
    function Cursor: string;

    // Add a comment to hash table before saving to disk. You can add as many
    // comment lines as you like. These comment lines are discarded when loading
    // the file. If you use a null format, all comments are deleted.
    procedure Comment(const Format: string);

    // Serialize hash table to a binary frame that can be sent in a message.
    // The packed format is compatible with the 'dictionary' type defined in
    // http://rfc.zeromq.org/spec:35/FILEMQ, and implemented by zproto:
    //
    //    ; A list of name/value pairs
    //    dictionary      = dict-count *( dict-name dict-value )
    //    dict-count      = number-4
    //    dict-value      = longstr
    //    dict-name       = string
    //
    //    ; Strings are always length + text contents
    //    longstr         = number-4 *VCHAR
    //    string          = number-1 *VCHAR
    //
    //    ; Numbers are unsigned integers in network byte order
    //    number-1        = 1OCTET
    //    number-4        = 4OCTET
    //
    // Comments are not included in the packed data. Item values MUST be
    // strings.
    function Pack: IZframe;

    // Save hash table to a text file in name=value format. Hash values must be
    // printable strings; keys may not contain '=' character. Returns 0 if OK,
    // else -1 if a file error occurred.
    function Save(const Filename: string): Integer;

    // Load hash table from a text file in name=value format; hash table must
    // already exist. Hash values must printable strings; keys may not contain
    // '=' character. Returns 0 if OK, else -1 if a file was not readable.
    function Load(const Filename: string): Integer;

    // When a hash table was loaded from a file by zhash_load, this method will
    // reload the file if it has been modified since, and is "stable", i.e. not
    // still changing. Returns 0 if OK, -1 if there was an error reloading the
    // file.
    function Refresh: Integer;

    // Set hash for automatic value destruction. Note that this assumes that
    // values are NULL-terminated strings. Do not use with different types.
    procedure Autofree;
  end;

  // extended generic type-free hash container
  TZhashx = class(TInterfacedObject, IZhashx)
  public
    FOwned: Boolean;
    FHandle: PZhashx;
    constructor Create(handle: PZhashx; owned: Boolean);
  public

    // Create a new, empty hash container
    constructor New;

    // Unpack binary frame into a new hash table. Packed data must follow format
    // defined by zhashx_pack. Hash table is set to autofree. An empty frame
    // unpacks to an empty hash table.
    constructor Unpack(const Frame: IZframe);

    // Same as unpack but uses a user-defined deserializer function to convert
    // a longstr back into item format.
    constructor UnpackOwn(const Frame: IZframe; Deserializer: TZhashxDeserializerFn);

    // Destroy a hash container and all items in it
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZhashx; owned: Boolean): IZhashx;
    class function UnWrap(const Value: IZhashx): PZhashx;
  protected

    // Insert item into hash table with specified key and item.
    // If key is already present returns -1 and leaves existing item unchanged
    // Returns 0 on success.
    function Insert(Key: Pointer; Item: Pointer): Integer;

    // Update or insert item into hash table with specified key and item. If the
    // key is already present, destroys old item and inserts new one. If you set
    // a container item destructor, this is called on the old value. If the key
    // was not already present, inserts a new item. Sets the hash cursor to the
    // new item.
    procedure Update(Key: Pointer; Item: Pointer);

    // Remove an item specified by key from the hash table. If there was no such
    // item, this function does nothing.
    procedure Delete(Key: Pointer);

    // Delete all items from the hash table. If the key destructor is
    // set, calls it on every key. If the item destructor is set, calls
    // it on every item.
    procedure Purge;

    // Return the item at the specified key, or null
    function Lookup(Key: Pointer): Pointer;

    // Reindexes an item from an old key to a new key. If there was no such
    // item, does nothing. Returns 0 if successful, else -1.
    function Rename(OldKey: Pointer; NewKey: Pointer): Integer;

    // Set a free function for the specified hash table item. When the item is
    // destroyed, the free function, if any, is called on that item.
    // Use this when hash items are dynamically allocated, to ensure that
    // you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
    // Returns the item, or NULL if there is no such item.
    function Freefn(Key: Pointer; FreeFn: TZhashxFreeFn): Pointer;

    // Return the number of keys/items in the hash table
    function Size: NativeUInt;

    // Return a zlistx_t containing the keys for the items in the
    // table. Uses the key_duplicator to duplicate all keys and sets the
    // key_destructor as destructor for the list.
    function Keys: IZlistx;

    // Return a zlistx_t containing the values for the items in the
    // table. Uses the duplicator to duplicate all items and sets the
    // destructor as destructor for the list.
    function Values: IZlistx;

    // Simple iterator; returns first item in hash table, in no given order,
    // or NULL if the table is empty. This method is simpler to use than the
    // foreach() method, which is deprecated. To access the key for this item
    // use zhashx_cursor(). NOTE: do NOT modify the table while iterating.
    function First: Pointer;

    // Simple iterator; returns next item in hash table, in no given order,
    // or NULL if the last item was already returned. Use this together with
    // zhashx_first() to process all items in a hash table. If you need the
    // items in sorted order, use zhashx_keys() and then zlistx_sort(). To
    // access the key for this item use zhashx_cursor(). NOTE: do NOT modify
    // the table while iterating.
    function Next: Pointer;

    // After a successful first/next method, returns the key for the item that
    // was returned. This is a constant string that you may not modify or
    // deallocate, and which lasts as long as the item in the hash. After an
    // unsuccessful first/next, returns NULL.
    function Cursor: Pointer;

    // Add a comment to hash table before saving to disk. You can add as many
    // comment lines as you like. These comment lines are discarded when loading
    // the file. If you use a null format, all comments are deleted.
    procedure Comment(const Format: string);

    // Save hash table to a text file in name=value format. Hash values must be
    // printable strings; keys may not contain '=' character. Returns 0 if OK,
    // else -1 if a file error occurred.
    function Save(const Filename: string): Integer;

    // Load hash table from a text file in name=value format; hash table must
    // already exist. Hash values must printable strings; keys may not contain
    // '=' character. Returns 0 if OK, else -1 if a file was not readable.
    function Load(const Filename: string): Integer;

    // When a hash table was loaded from a file by zhashx_load, this method will
    // reload the file if it has been modified since, and is "stable", i.e. not
    // still changing. Returns 0 if OK, -1 if there was an error reloading the
    // file.
    function Refresh: Integer;

    // Serialize hash table to a binary frame that can be sent in a message.
    // The packed format is compatible with the 'dictionary' type defined in
    // http://rfc.zeromq.org/spec:35/FILEMQ, and implemented by zproto:
    //
    //    ; A list of name/value pairs
    //    dictionary      = dict-count *( dict-name dict-value )
    //    dict-count      = number-4
    //    dict-value      = longstr
    //    dict-name       = string
    //
    //    ; Strings are always length + text contents
    //    longstr         = number-4 *VCHAR
    //    string          = number-1 *VCHAR
    //
    //    ; Numbers are unsigned integers in network byte order
    //    number-1        = 1OCTET
    //    number-4        = 4OCTET
    //
    // Comments are not included in the packed data. Item values MUST be
    // strings.
    function Pack: IZframe;

    // Same as pack but uses a user-defined serializer function to convert items
    // into longstr.
    function PackOwn(Serializer: TZhashxSerializerFn): IZframe;

    // Make a copy of the list; items are duplicated if you set a duplicator
    // for the list, otherwise not. Copying a null reference returns a null
    // reference. Note that this method's behavior changed slightly for CZMQ
    // v3.x, as it does not set nor respect autofree. It does however let you
    // duplicate any hash table safely. The old behavior is in zhashx_dup_v2.
    function Dup: IZhashx;

    // Set a user-defined deallocator for hash items; by default items are not
    // freed when the hash is destroyed.
    procedure SetDestructor(&Destructor: TZhashxDestructorFn);

    // Set a user-defined duplicator for hash items; by default items are not
    // copied when the hash is duplicated.
    procedure SetDuplicator(Duplicator: TZhashxDuplicatorFn);

    // Set a user-defined deallocator for keys; by default keys are freed
    // when the hash is destroyed using free().
    procedure SetKeyDestructor(&Destructor: TZhashxDestructorFn);

    // Set a user-defined duplicator for keys; by default keys are duplicated
    // using strdup.
    procedure SetKeyDuplicator(Duplicator: TZhashxDuplicatorFn);

    // Set a user-defined comparator for keys; by default keys are
    // compared using strcmp.
    // The callback function should return zero (0) on matching
    // items.
    procedure SetKeyComparator(Comparator: TZhashxComparatorFn);

    // Set a user-defined hash function for keys; by default keys are
    // hashed by a modified Bernstein hashing function.
    procedure SetKeyHasher(Hasher: TZhashxHashFn);

    // Make copy of hash table; if supplied table is null, returns null.
    // Does not copy items themselves. Rebuilds new table so may be slow on
    // very large tables. NOTE: only works with item values that are strings
    // since there's no other way to know how to duplicate the item value.
    function DupV2: IZhashx;
  end;

  // List of network interfaces available on system
  TZiflist = class(TInterfacedObject, IZiflist)
  public
    FOwned: Boolean;
    FHandle: PZiflist;
    constructor Create(handle: PZiflist; owned: Boolean);
  public

    // Get a list of network interfaces currently defined on the system
    constructor New;

    // Destroy a ziflist instance
    destructor Destroy; override;

    // Get a list of network interfaces currently defined on the system
    // Includes IPv6 interfaces
    class function NewIpv6: IZiflist;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZiflist; owned: Boolean): IZiflist;
    class function UnWrap(const Value: IZiflist): PZiflist;
  protected

    // Reload network interfaces from system
    procedure Reload;

    // Return the number of network interfaces on system
    function Size: NativeUInt;

    // Get first network interface, return NULL if there are none
    function First: string;

    // Get next network interface, return NULL if we hit the last one
    function Next: string;

    // Return the current interface IP address as a printable string
    function Address: string;

    // Return the current interface broadcast address as a printable string
    function Broadcast: string;

    // Return the current interface network mask as a printable string
    function Netmask: string;

    // Return the list of interfaces.
    procedure Print;

    // Reload network interfaces from system, including IPv6
    procedure ReloadIpv6;

    // Return true if the current interface uses IPv6
    function IsIpv6: Boolean;
  end;

  // simple generic list container
  TZlist = class(TInterfacedObject, IZlist)
  public
    FOwned: Boolean;
    FHandle: PZlist;
    constructor Create(handle: PZlist; owned: Boolean);
  public

    // Create a new list container
    constructor New;

    // Destroy a list container
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZlist; owned: Boolean): IZlist;
    class function UnWrap(const Value: IZlist): PZlist;
  protected

    // Return the item at the head of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the head item, or NULL if the list is empty.
    function First: Pointer;

    // Return the next item. If the list is empty, returns NULL. To move to
    // the start of the list call zlist_first (). Advances the cursor.
    function Next: Pointer;

    // Return the item at the tail of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the tail item, or NULL if the list is empty.
    function Last: Pointer;

    // Return first item in the list, or null, leaves the cursor
    function Head: Pointer;

    // Return last item in the list, or null, leaves the cursor
    function Tail: Pointer;

    // Return the current item of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the current item, or NULL if the list is empty.
    function Item: Pointer;

    // Append an item to the end of the list, return 0 if OK or -1 if this
    // failed for some reason (out of memory). Note that if a duplicator has
    // been set, this method will also duplicate the item.
    function Append(Item: Pointer): Integer;

    // Push an item to the start of the list, return 0 if OK or -1 if this
    // failed for some reason (out of memory). Note that if a duplicator has
    // been set, this method will also duplicate the item.
    function Push(Item: Pointer): Integer;

    // Pop the item off the start of the list, if any
    function Pop: Pointer;

    // Checks if an item already is present. Uses compare method to determine if
    // items are equal. If the compare method is NULL the check will only compare
    // pointers. Returns true if item is present else false.
    function Exists(Item: Pointer): Boolean;

    // Remove the specified item from the list if present
    procedure Remove(Item: Pointer);

    // Make a copy of list. If the list has autofree set, the copied list will
    // duplicate all items, which must be strings. Otherwise, the list will hold
    // pointers back to the items in the original list. If list is null, returns
    // NULL.
    function Dup: IZlist;

    // Purge all items from list
    procedure Purge;

    // Return number of items in the list
    function Size: NativeUInt;

    // Sort the list. If the compare function is null, sorts the list by
    // ascending key value using a straight ASCII comparison. If you specify
    // a compare function, this decides how items are sorted. The sort is not
    // stable, so may reorder items with the same keys. The algorithm used is
    // combsort, a compromise between performance and simplicity.
    procedure Sort(Compare: TZlistCompareFn);

    // Set list for automatic item destruction; item values MUST be strings.
    // By default a list item refers to a value held elsewhere. When you set
    // this, each time you append or push a list item, zlist will take a copy
    // of the string value. Then, when you destroy the list, it will free all
    // item values automatically. If you use any other technique to allocate
    // list values, you must free them explicitly before destroying the list.
    // The usual technique is to pop list items and destroy them, until the
    // list is empty.
    procedure Autofree;

    // Sets a compare function for this list. The function compares two items.
    // It returns an integer less than, equal to, or greater than zero if the
    // first item is found, respectively, to be less than, to match, or be
    // greater than the second item.
    // This function is used for sorting, removal and exists checking.
    procedure Comparefn(Fn: TZlistCompareFn);

    // Set a free function for the specified list item. When the item is
    // destroyed, the free function, if any, is called on that item.
    // Use this when list items are dynamically allocated, to ensure that
    // you don't have memory leaks. You can pass 'free' or NULL as a free_fn.
    // Returns the item, or NULL if there is no such item.
    function Freefn(Item: Pointer; Fn: TZlistFreeFn; AtTail: Boolean): Pointer;
  end;

  // extended generic list container
  TZlistx = class(TInterfacedObject, IZlistx)
  public
    FOwned: Boolean;
    FHandle: PZlistx;
    constructor Create(handle: PZlistx; owned: Boolean);
  public

    // Create a new, empty list.
    constructor New;

    // Unpack binary frame into a new list. Packed data must follow format
    // defined by zlistx_pack. List is set to autofree. An empty frame
    // unpacks to an empty list.
    constructor Unpack(const Frame: IZframe);

    // Destroy a list. If an item destructor was specified, all items in the
    // list are automatically destroyed as well.
    destructor Destroy; override;

    // Returns the item associated with the given list handle, or NULL if passed
    // in handle is NULL. Asserts that the passed in handle points to a list element.
    class function HandleItem(Handle: Pointer): Pointer;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZlistx; owned: Boolean): IZlistx;
    class function UnWrap(const Value: IZlistx): PZlistx;
  protected

    // Add an item to the head of the list. Calls the item duplicator, if any,
    // on the item. Resets cursor to list head. Returns an item handle on
    // success, NULL if memory was exhausted.
    function AddStart(Item: Pointer): Pointer;

    // Add an item to the tail of the list. Calls the item duplicator, if any,
    // on the item. Resets cursor to list head. Returns an item handle on
    // success, NULL if memory was exhausted.
    function AddEnd(Item: Pointer): Pointer;

    // Return the number of items in the list
    function Size: NativeUInt;

    // Return first item in the list, or null, leaves the cursor
    function Head: Pointer;

    // Return last item in the list, or null, leaves the cursor
    function Tail: Pointer;

    // Return the item at the head of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the head item, or NULL if the list is empty.
    function First: Pointer;

    // Return the next item. At the end of the list (or in an empty list),
    // returns NULL. Use repeated zlistx_next () calls to work through the list
    // from zlistx_first (). First time, acts as zlistx_first().
    function Next: Pointer;

    // Return the previous item. At the start of the list (or in an empty list),
    // returns NULL. Use repeated zlistx_prev () calls to work through the list
    // backwards from zlistx_last (). First time, acts as zlistx_last().
    function Prev: Pointer;

    // Return the item at the tail of list. If the list is empty, returns NULL.
    // Leaves cursor pointing at the tail item, or NULL if the list is empty.
    function Last: Pointer;

    // Returns the value of the item at the cursor, or NULL if the cursor is
    // not pointing to an item.
    function Item: Pointer;

    // Returns the handle of the item at the cursor, or NULL if the cursor is
    // not pointing to an item.
    function Cursor: Pointer;

    // Find an item in the list, searching from the start. Uses the item
    // comparator, if any, else compares item values directly. Returns the
    // item handle found, or NULL. Sets the cursor to the found item, if any.
    function Find(Item: Pointer): Pointer;

    // Detach an item from the list, using its handle. The item is not modified,
    // and the caller is responsible for destroying it if necessary. If handle is
    // null, detaches the first item on the list. Returns item that was detached,
    // or null if none was. If cursor was at item, moves cursor to previous item,
    // so you can detach items while iterating forwards through a list.
    function Detach(Handle: Pointer): Pointer;

    // Detach item at the cursor, if any, from the list. The item is not modified,
    // and the caller is responsible for destroying it as necessary. Returns item
    // that was detached, or null if none was. Moves cursor to previous item, so
    // you can detach items while iterating forwards through a list.
    function DetachCur: Pointer;

    // Delete an item, using its handle. Calls the item destructor if any is
    // set. If handle is null, deletes the first item on the list. Returns 0
    // if an item was deleted, -1 if not. If cursor was at item, moves cursor
    // to previous item, so you can delete items while iterating forwards
    // through a list.
    function Delete(Handle: Pointer): Integer;

    // Move an item to the start of the list, via its handle.
    procedure MoveStart(Handle: Pointer);

    // Move an item to the end of the list, via its handle.
    procedure MoveEnd(Handle: Pointer);

    // Remove all items from the list, and destroy them if the item destructor
    // is set.
    procedure Purge;

    // Sort the list. If an item comparator was set, calls that to compare
    // items, otherwise compares on item value. The sort is not stable, so may
    // reorder equal items.
    procedure Sort;

    // Create a new node and insert it into a sorted list. Calls the item
    // duplicator, if any, on the item. If low_value is true, starts searching
    // from the start of the list, otherwise searches from the end. Use the item
    // comparator, if any, to find where to place the new node. Returns a handle
    // to the new node, or NULL if memory was exhausted. Resets the cursor to the
    // list head.
    function Insert(Item: Pointer; LowValue: Boolean): Pointer;

    // Move an item, specified by handle, into position in a sorted list. Uses
    // the item comparator, if any, to determine the new location. If low_value
    // is true, starts searching from the start of the list, otherwise searches
    // from the end.
    procedure Reorder(Handle: Pointer; LowValue: Boolean);

    // Make a copy of the list; items are duplicated if you set a duplicator
    // for the list, otherwise not. Copying a null reference returns a null
    // reference.
    function Dup: IZlistx;

    // Set a user-defined deallocator for list items; by default items are not
    // freed when the list is destroyed.
    procedure SetDestructor(&Destructor: TZlistxDestructorFn);

    // Set a user-defined duplicator for list items; by default items are not
    // copied when the list is duplicated.
    procedure SetDuplicator(Duplicator: TZlistxDuplicatorFn);

    // Set a user-defined comparator for zlistx_find and zlistx_sort; the method
    // must return -1, 0, or 1 depending on whether item1 is less than, equal to,
    // or greater than, item2.
    procedure SetComparator(Comparator: TZlistxComparatorFn);

    // Serialize list to a binary frame that can be sent in a message.
    // The packed format is compatible with the 'strings' type implemented by zproto:
    //
    //    ; A list of strings
    //    list            = list-count *longstr
    //    list-count      = number-4
    //
    //    ; Strings are always length + text contents
    //    longstr         = number-4 *VCHAR
    //
    //    ; Numbers are unsigned integers in network byte order
    //    number-4        = 4OCTET
    function Pack: IZframe;
  end;

  // event-driven reactor
  TZloop = class(TInterfacedObject, IZloop)
  public
    FOwned: Boolean;
    FHandle: PZloop;
    constructor Create(handle: PZloop; owned: Boolean);
  public

    // Create a new zloop reactor
    constructor New;

    // Destroy a reactor
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZloop; owned: Boolean): IZloop;
    class function UnWrap(const Value: IZloop): PZloop;
  protected

    // Register socket reader with the reactor. When the reader has messages,
    // the reactor will call the handler, passing the arg. Returns 0 if OK, -1
    // if there was an error. If you register the same socket more than once,
    // each instance will invoke its corresponding handler.
    function Reader(const Sock: IZsock; Handler: TZloopReaderFn; Arg: Pointer): Integer;

    // Cancel a socket reader from the reactor. If multiple readers exist for
    // same socket, cancels ALL of them.
    procedure ReaderEnd(const Sock: IZsock);

    // Configure a registered reader to ignore errors. If you do not set this,
    // then readers that have errors are removed from the reactor silently.
    procedure ReaderSetTolerant(const Sock: IZsock);

    // Register low-level libzmq pollitem with the reactor. When the pollitem
    // is ready, will call the handler, passing the arg. Returns 0 if OK, -1
    // if there was an error. If you register the pollitem more than once, each
    // instance will invoke its corresponding handler. A pollitem with
    // socket=NULL and fd=0 means 'poll on FD zero'.
    function Poller(Item: Pointer; Handler: TZloopFn; Arg: Pointer): Integer;

    // Cancel a pollitem from the reactor, specified by socket or FD. If both
    // are specified, uses only socket. If multiple poll items exist for same
    // socket/FD, cancels ALL of them.
    procedure PollerEnd(Item: Pointer);

    // Configure a registered poller to ignore errors. If you do not set this,
    // then poller that have errors are removed from the reactor silently.
    procedure PollerSetTolerant(Item: Pointer);

    // Register a timer that expires after some delay and repeats some number of
    // times. At each expiry, will call the handler, passing the arg. To run a
    // timer forever, use 0 times. Returns a timer_id that is used to cancel the
    // timer in the future. Returns -1 if there was an error.
    function Timer(Delay: NativeUInt; Times: NativeUInt; Handler: TZloopTimerFn; Arg: Pointer): Integer;

    // Cancel a specific timer identified by a specific timer_id (as returned by
    // zloop_timer).
    function TimerEnd(TimerId: Integer): Integer;

    // Register a ticket timer. Ticket timers are very fast in the case where
    // you use a lot of timers (thousands), and frequently remove and add them.
    // The main use case is expiry timers for servers that handle many clients,
    // and which reset the expiry timer for each message received from a client.
    // Whereas normal timers perform poorly as the number of clients grows, the
    // cost of ticket timers is constant, no matter the number of clients. You
    // must set the ticket delay using zloop_set_ticket_delay before creating a
    // ticket. Returns a handle to the timer that you should use in
    // zloop_ticket_reset and zloop_ticket_delete.
    function Ticket(Handler: TZloopTimerFn; Arg: Pointer): Pointer;

    // Reset a ticket timer, which moves it to the end of the ticket list and
    // resets its execution time. This is a very fast operation.
    procedure TicketReset(Handle: Pointer);

    // Delete a ticket timer. We do not actually delete the ticket here, as
    // other code may still refer to the ticket. We mark as deleted, and remove
    // later and safely.
    procedure TicketDelete(Handle: Pointer);

    // Set the ticket delay, which applies to all tickets. If you lower the
    // delay and there are already tickets created, the results are undefined.
    procedure SetTicketDelay(TicketDelay: NativeUInt);

    // Set hard limit on number of timers allowed. Setting more than a small
    // number of timers (10-100) can have a dramatic impact on the performance
    // of the reactor. For high-volume cases, use ticket timers. If the hard
    // limit is reached, the reactor stops creating new timers and logs an
    // error.
    procedure SetMaxTimers(MaxTimers: NativeUInt);

    // Set verbose tracing of reactor on/off. The default verbose setting is
    // off (false).
    procedure SetVerbose(Verbose: Boolean);

    // By default the reactor stops if the process receives a SIGINT or SIGTERM
    // signal. This makes it impossible to shut-down message based architectures
    // like zactors. This method lets you switch off break handling. The default
    // nonstop setting is off (false).
    procedure SetNonstop(Nonstop: Boolean);

    // Start the reactor. Takes control of the thread and returns when the 0MQ
    // context is terminated or the process is interrupted, or any event handler
    // returns -1. Event handlers may register new sockets and timers, and
    // cancel sockets. Returns 0 if interrupted, -1 if canceled by a handler.
    function Start: Integer;
  end;

  // working with multipart messages
  TZmsg = class(TInterfacedObject, IZmsg)
  public
    FOwned: Boolean;
    FHandle: PZmsg;
    constructor Create(handle: PZmsg; owned: Boolean);
  public

    // Create a new empty message object
    constructor New;

    // Receive message from socket, returns zmsg_t object or NULL if the recv
    // was interrupted. Does a blocking recv. If you want to not block then use
    // the zloop class or zmsg_recv_nowait or zmq_poll to check for socket input
    // before receiving.
    constructor Recv(const Source: IZSock);

    // Load/append an open file into new message, return the message.
    // Returns NULL if the message could not be loaded.
    constructor Load(&File: Pointer);

    // Decodes a serialized message frame created by zmsg_encode () and returns
    // a new zmsg_t object. Returns NULL if the frame was badly formatted or
    // there was insufficient memory to work.
    constructor Decode(const Frame: IZframe);

    // Generate a signal message encoding the given status. A signal is a short
    // message carrying a 1-byte success/failure code (by convention, 0 means
    // OK). Signals are encoded to be distinguishable from "normal" messages.
    constructor NewSignal(Status: Byte);

    // Destroy a message object and all frames it contains
    destructor Destroy; override;

    // Send message to destination socket, and destroy the message after sending
    // it successfully. If the message has no frames, sends nothing but destroys
    // the message anyhow. Nullifies the caller's reference to the message (as
    // it is a destructor).
    class function Send(var SelfP: IZmsg; const Dest: IZSock): Integer;

    // Send message to destination socket as part of a multipart sequence, and
    // destroy the message after sending it successfully. Note that after a
    // zmsg_sendm, you must call zmsg_send or another method that sends a final
    // message part. If the message has no frames, sends nothing but destroys
    // the message anyhow. Nullifies the caller's reference to the message (as
    // it is a destructor).
    class function Sendm(var SelfP: IZmsg; const Dest: IZSock): Integer;

    // Probe the supplied object, and report if it looks like a zmsg_t.
    class function &Is(This: Pointer): Boolean;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZmsg; owned: Boolean): IZmsg;
    class function UnWrap(const Value: IZmsg): PZmsg;
  protected

    // Return size of message, i.e. number of frames (0 or more).
    function Size: NativeUInt;

    // Return total size of all frames in message.
    function ContentSize: NativeUInt;

    // Return message routing ID, if the message came from a ZMQ_SERVER socket.
    // Else returns zero.
    function RoutingId: Cardinal;

    // Set routing ID on message. This is used if/when the message is sent to a
    // ZMQ_SERVER socket.
    procedure SetRoutingId(RoutingId: Cardinal);

    // Push frame to the front of the message, i.e. before all other frames.
    // Message takes ownership of frame, will destroy it when message is sent.
    // Returns 0 on success, -1 on error. Deprecates zmsg_push, which did not
    // nullify the caller's frame reference.
    function Prepend(var FrameP: IZframe): Integer;

    // Add frame to the end of the message, i.e. after all other frames.
    // Message takes ownership of frame, will destroy it when message is sent.
    // Returns 0 on success. Deprecates zmsg_add, which did not nullify the
    // caller's frame reference.
    function Append(var FrameP: IZframe): Integer;

    // Remove first frame from message, if any. Returns frame, or NULL.
    function Pop: IZframe;

    // Push block of memory to front of message, as a new frame.
    // Returns 0 on success, -1 on error.
    function Pushmem(Data: PByte; Size: NativeUInt): Integer;

    // Add block of memory to the end of the message, as a new frame.
    // Returns 0 on success, -1 on error.
    function Addmem(Data: PByte; Size: NativeUInt): Integer;

    // Push string as new frame to front of message.
    // Returns 0 on success, -1 on error.
    function Pushstr(const &String: string): Integer;

    // Push string as new frame to end of message.
    // Returns 0 on success, -1 on error.
    function Addstr(const &String: string): Integer;

    // Push formatted string as new frame to front of message.
    // Returns 0 on success, -1 on error.
    function Pushstrf(const Format: string): Integer;

    // Push formatted string as new frame to end of message.
    // Returns 0 on success, -1 on error.
    function Addstrf(const Format: string): Integer;

    // Pop frame off front of message, return as fresh string. If there were
    // no more frames in the message, returns NULL.
    function Popstr: string;

    // Push encoded message as a new frame. Message takes ownership of
    // submessage, so the original is destroyed in this call. Returns 0 on
    // success, -1 on error.
    function Addmsg(var MsgP: IZmsg): Integer;

    // Remove first submessage from message, if any. Returns zmsg_t, or NULL if
    // decoding was not successful.
    function Popmsg: IZmsg;

    // Remove specified frame from list, if present. Does not destroy frame.
    procedure Remove(const Frame: IZframe);

    // Set cursor to first frame in message. Returns frame, or NULL, if the
    // message is empty. Use this to navigate the frames as a list.
    function First: IZframe;

    // Return the next frame. If there are no more frames, returns NULL. To move
    // to the first frame call zmsg_first(). Advances the cursor.
    function Next: IZframe;

    // Return the last frame. If there are no frames, returns NULL.
    function Last: IZframe;

    // Save message to an open file, return 0 if OK, else -1. The message is
    // saved as a series of frames, each with length and data. Note that the
    // file is NOT guaranteed to be portable between operating systems, not
    // versions of CZMQ. The file format is at present undocumented and liable
    // to arbitrary change.
    function Save(&File: Pointer): Integer;

    // Serialize multipart message to a single message frame. Use this method
    // to send structured messages across transports that do not support
    // multipart data. Allocates and returns a new frame containing the
    // serialized message. To decode a serialized message frame, use
    // zmsg_decode ().
    function Encode: IZframe;

    // Create copy of message, as new message object. Returns a fresh zmsg_t
    // object. If message is null, or memory was exhausted, returns null.
    function Dup: IZmsg;

    // Send message to zsys log sink (may be stdout, or system facility as
    // configured by zsys_set_logstream).
    procedure Print;

    // Return true if the two messages have the same number of frames and each
    // frame in the first message is identical to the corresponding frame in the
    // other message. As with zframe_eq, return false if either message is NULL.
    function Eq(const Other: IZmsg): Boolean;

    // Return signal value, 0 or greater, if message is a signal, -1 if not.
    function Signal: Integer;
  end;

  // event-driven reactor
  TZpoller = class(TInterfacedObject, IZpoller)
  public
    FOwned: Boolean;
    FHandle: PZpoller;
    constructor Create(handle: PZpoller; owned: Boolean);
  public

    // Create new poller, specifying zero or more readers. The list of
    // readers ends in a NULL. Each reader can be a zsock_t instance, a
    // zactor_t instance, a libzmq socket (void *), or a file handle.
    constructor New(const Reader: IZSock);

    // Destroy a poller
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZpoller; owned: Boolean): IZpoller;
    class function UnWrap(const Value: IZpoller): PZpoller;
  protected

    // Add a reader to be polled. Returns 0 if OK, -1 on failure. The reader may
    // be a libzmq void * socket, a zsock_t instance, a zactor_t instance or a
    // file handle.
    function Add(const Reader: IZSock): Integer;

    // Remove a reader from the poller; returns 0 if OK, -1 on failure. The reader
    // must have been passed during construction, or in an zpoller_add () call.
    function Remove(Reader: Pointer): Integer;

    // By default the poller stops if the process receives a SIGINT or SIGTERM
    // signal. This makes it impossible to shut-down message based architectures
    // like zactors. This method lets you switch off break handling. The default
    // nonstop setting is off (false).
    procedure SetNonstop(Nonstop: Boolean);

    // Poll the registered readers for I/O, return first reader that has input.
    // The reader will be a libzmq void * socket, a zsock_t, a zactor_t
    // instance or a file handle as specified in zpoller_new/zpoller_add. The
    // timeout should be zero or greater, or -1 to wait indefinitely. Socket
    // priority is defined by their order in the poll list. If you need a
    // balanced poll, use the low level zmq_poll method directly. If the poll
    // call was interrupted (SIGINT), or the ZMQ context was destroyed, or the
    // timeout expired, returns NULL. You can test the actual exit condition by
    // calling zpoller_expired () and zpoller_terminated (). The timeout is in
    // msec.
    function Wait(Timeout: Integer): IZSock;

    // Return true if the last zpoller_wait () call ended because the timeout
    // expired, without any error.
    function Expired: Boolean;

    // Return true if the last zpoller_wait () call ended because the process
    // was interrupted, or the parent context was destroyed.
    function Terminated: Boolean;
  end;

  // high-level socket API that hides libzmq contexts and sockets
  TZsock = class(TInterfacedObject, IZsock)
  public
    FOwned: Boolean;
    FHandle: PZsock;
    constructor Create(handle: PZsock; owned: Boolean);
  public

    // Create a new socket. Returns the new socket, or NULL if the new socket
    // could not be created. Note that the symbol zsock_new (and other
    // constructors/destructors for zsock) are redirected to the *_checked
    // variant, enabling intelligent socket leak detection. This can have
    // performance implications if you use a LOT of sockets. To turn off this
    // redirection behaviour, define ZSOCK_NOCHECK.
    constructor New(&Type: Integer);

    // Create a PUB socket. Default action is bind.
    constructor NewPub(const Endpoint: string);

    // Create a SUB socket, and optionally subscribe to some prefix string. Default
    // action is connect.
    constructor NewSub(const Endpoint: string; const Subscribe: string);

    // Create a REQ socket. Default action is connect.
    constructor NewReq(const Endpoint: string);

    // Create a REP socket. Default action is bind.
    constructor NewRep(const Endpoint: string);

    // Create a DEALER socket. Default action is connect.
    constructor NewDealer(const Endpoint: string);

    // Create a ROUTER socket. Default action is bind.
    constructor NewRouter(const Endpoint: string);

    // Create a PUSH socket. Default action is connect.
    constructor NewPush(const Endpoint: string);

    // Create a PULL socket. Default action is bind.
    constructor NewPull(const Endpoint: string);

    // Create an XPUB socket. Default action is bind.
    constructor NewXpub(const Endpoint: string);

    // Create an XSUB socket. Default action is connect.
    constructor NewXsub(const Endpoint: string);

    // Create a PAIR socket. Default action is connect.
    constructor NewPair(const Endpoint: string);

    // Create a STREAM socket. Default action is connect.
    constructor NewStream(const Endpoint: string);

    // Create a SERVER socket. Default action is bind.
    constructor NewServer(const Endpoint: string);

    // Create a CLIENT socket. Default action is connect.
    constructor NewClient(const Endpoint: string);

    // Create a RADIO socket. Default action is bind.
    constructor NewRadio(const Endpoint: string);

    // Create a DISH socket. Default action is connect.
    constructor NewDish(const Endpoint: string);

    // Create a GATHER socket. Default action is bind.
    constructor NewGather(const Endpoint: string);

    // Create a SCATTER socket. Default action is connect.
    constructor NewScatter(const Endpoint: string);

    // Destroy the socket. You must use this for any socket created via the
    // zsock_new method.
    destructor Destroy; override;

    // Probe the supplied object, and report if it looks like a zsock_t.
    // Takes a polymorphic socket reference.
    class function &Is(This: Pointer): Boolean;

    // Probe the supplied reference. If it looks like a zsock_t instance, return
    // the underlying libzmq socket handle; else if it looks like a file
    // descriptor, return NULL; else if it looks like a libzmq socket handle,
    // return the supplied value. Takes a polymorphic socket reference.
    class function Resolve(This: Pointer): Pointer;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZsock; owned: Boolean): IZsock;
    class function UnWrap(const Value: IZsock): PZsock;
  protected

    // Bind a socket to a formatted endpoint. For tcp:// endpoints, supports
    // ephemeral ports, if you specify the port number as "*". By default
    // zsock uses the IANA designated range from C000 (49152) to FFFF (65535).
    // To override this range, follow the "*" with "[first-last]". Either or
    // both first and last may be empty. To bind to a random port within the
    // range, use "!" in place of "*".
    //
    // Examples:
    //     tcp://127.0.0.1:*           bind to first free port from C000 up
    //     tcp://127.0.0.1:!           bind to random port from C000 to FFFF
    //     tcp://127.0.0.1:*[60000-]   bind to first free port from 60000 up
    //     tcp://127.0.0.1:![-60000]   bind to random port from C000 to 60000
    //     tcp://127.0.0.1:![55000-55999]
    //                                 bind to random port from 55000 to 55999
    //
    // On success, returns the actual port number used, for tcp:// endpoints,
    // and 0 for other transports. On failure, returns -1. Note that when using
    // ephemeral ports, a port may be reused by different services without
    // clients being aware. Protocols that run on ephemeral ports should take
    // this into account.
    function Bind(const Format: string): Integer;

    // Returns last bound endpoint, if any.
    function Endpoint: string;

    // Unbind a socket from a formatted endpoint.
    // Returns 0 if OK, -1 if the endpoint was invalid or the function
    // isn't supported.
    function Unbind(const Format: string): Integer;

    // Connect a socket to a formatted endpoint
    // Returns 0 if OK, -1 if the endpoint was invalid.
    function Connect(const Format: string): Integer;

    // Disconnect a socket from a formatted endpoint
    // Returns 0 if OK, -1 if the endpoint was invalid or the function
    // isn't supported.
    function Disconnect(const Format: string): Integer;

    // Attach a socket to zero or more endpoints. If endpoints is not null,
    // parses as list of ZeroMQ endpoints, separated by commas, and prefixed by
    // '@' (to bind the socket) or '>' (to connect the socket). Returns 0 if all
    // endpoints were valid, or -1 if there was a syntax error. If the endpoint
    // does not start with '@' or '>', the serverish argument defines whether
    // it is used to bind (serverish = true) or connect (serverish = false).
    function Attach(const Endpoints: string; Serverish: Boolean): Integer;

    // Returns socket type as printable constant string.
    function TypeStr: string;

    // Send a 'picture' message to the socket (or actor). The picture is a
    // string that defines the type of each frame. This makes it easy to send
    // a complex multiframe message in one call. The picture can contain any
    // of these characters, each corresponding to one or two arguments:
    //
    //     i = int (signed)
    //     1 = uint8_t
    //     2 = uint16_t
    //     4 = uint32_t
    //     8 = uint64_t
    //     s = char *
    //     b = byte *, size_t (2 arguments)
    //     c = zchunk_t *
    //     f = zframe_t *
    //     h = zhashx_t *
    //     l = zlistx_t * (DRAFT)
    //     U = zuuid_t *
    //     p = void * (sends the pointer value, only meaningful over inproc)
    //     m = zmsg_t * (sends all frames in the zmsg)
    //     z = sends zero-sized frame (0 arguments)
    //     u = uint (deprecated)
    //
    // Note that s, b, c, and f are encoded the same way and the choice is
    // offered as a convenience to the sender, which may or may not already
    // have data in a zchunk or zframe. Does not change or take ownership of
    // any arguments. Returns 0 if successful, -1 if sending failed for any
    // reason.
    function Send(const Picture: string): Integer;

    // Send a 'picture' message to the socket (or actor). This is a va_list
    // version of zsock_send (), so please consult its documentation for the
    // details.
    function Vsend(const Picture: string; Argptr: va_list): Integer;

    // Receive a 'picture' message to the socket (or actor). See zsock_send for
    // the format and meaning of the picture. Returns the picture elements into
    // a series of pointers as provided by the caller:
    //
    //     i = int * (stores signed integer)
    //     4 = uint32_t * (stores 32-bit unsigned integer)
    //     8 = uint64_t * (stores 64-bit unsigned integer)
    //     s = char ** (allocates new string)
    //     b = byte **, size_t * (2 arguments) (allocates memory)
    //     c = zchunk_t ** (creates zchunk)
    //     f = zframe_t ** (creates zframe)
    //     U = zuuid_t * (creates a zuuid with the data)
    //     h = zhashx_t ** (creates zhashx)
    //     l = zlistx_t ** (creates zlistx) (DRAFT)
    //     p = void ** (stores pointer)
    //     m = zmsg_t ** (creates a zmsg with the remaining frames)
    //     z = null, asserts empty frame (0 arguments)
    //     u = uint * (stores unsigned integer, deprecated)
    //
    // Note that zsock_recv creates the returned objects, and the caller must
    // destroy them when finished with them. The supplied pointers do not need
    // to be initialized. Returns 0 if successful, or -1 if it failed to recv
    // a message, in which case the pointers are not modified. When message
    // frames are truncated (a short message), sets return values to zero/null.
    // If an argument pointer is NULL, does not store any value (skips it).
    // An 'n' picture matches an empty frame; if the message does not match,
    // the method will return -1.
    function Recv(const Picture: string): Integer;

    // Receive a 'picture' message from the socket (or actor). This is a
    // va_list version of zsock_recv (), so please consult its documentation
    // for the details.
    function Vrecv(const Picture: string; Argptr: va_list): Integer;

    // Send a binary encoded 'picture' message to the socket (or actor). This
    // method is similar to zsock_send, except the arguments are encoded in a
    // binary format that is compatible with zproto, and is designed to reduce
    // memory allocations. The pattern argument is a string that defines the
    // type of each argument. Supports these argument types:
    //
    //  pattern    C type                  zproto type:
    //     1       uint8_t                 type = "number" size = "1"
    //     2       uint16_t                type = "number" size = "2"
    //     4       uint32_t                type = "number" size = "3"
    //     8       uint64_t                type = "number" size = "4"
    //     s       char *, 0-255 chars     type = "string"
    //     S       char *, 0-2^32-1 chars  type = "longstr"
    //     c       zchunk_t *              type = "chunk"
    //     f       zframe_t *              type = "frame"
    //     u       zuuid_t *               type = "uuid"
    //     m       zmsg_t *                type = "msg"
    //     p       void *, sends pointer value, only over inproc
    //
    // Does not change or take ownership of any arguments. Returns 0 if
    // successful, -1 if sending failed for any reason.
    function Bsend(const Picture: string): Integer;

    // Receive a binary encoded 'picture' message from the socket (or actor).
    // This method is similar to zsock_recv, except the arguments are encoded
    // in a binary format that is compatible with zproto, and is designed to
    // reduce memory allocations. The pattern argument is a string that defines
    // the type of each argument. See zsock_bsend for the supported argument
    // types. All arguments must be pointers; this call sets them to point to
    // values held on a per-socket basis.
    // For types 1, 2, 4 and 8 the caller must allocate the memory itself before
    // calling zsock_brecv.
    // For types S, the caller must free the value once finished with it, as
    // zsock_brecv will allocate the buffer.
    // For type s, the caller must not free the value as it is stored in a
    // local cache for performance purposes.
    // For types c, f, u and m the caller must call the appropriate destructor
    // depending on the object as zsock_brecv will create new objects.
    // For type p the caller must coordinate with the sender, as it is just a
    // pointer value being passed.
    function Brecv(const Picture: string): Integer;

    // Return socket routing ID if any. This returns 0 if the socket is not
    // of type ZMQ_SERVER or if no request was already received on it.
    function RoutingId: Cardinal;

    // Set routing ID on socket. The socket MUST be of type ZMQ_SERVER.
    // This will be used when sending messages on the socket via the zsock API.
    procedure SetRoutingId(RoutingId: Cardinal);

    // Set socket to use unbounded pipes (HWM=0); use this in cases when you are
    // totally certain the message volume can fit in memory. This method works
    // across all versions of ZeroMQ. Takes a polymorphic socket reference.
    procedure SetUnbounded;

    // Send a signal over a socket. A signal is a short message carrying a
    // success/failure code (by convention, 0 means OK). Signals are encoded
    // to be distinguishable from "normal" messages. Accepts a zsock_t or a
    // zactor_t argument, and returns 0 if successful, -1 if the signal could
    // not be sent. Takes a polymorphic socket reference.
    function Signal(Status: Byte): Integer;

    // Wait on a signal. Use this to coordinate between threads, over pipe
    // pairs. Blocks until the signal is received. Returns -1 on error, 0 or
    // greater on success. Accepts a zsock_t or a zactor_t as argument.
    // Takes a polymorphic socket reference.
    function Wait: Integer;

    // If there is a partial message still waiting on the socket, remove and
    // discard it. This is useful when reading partial messages, to get specific
    // message types.
    procedure Flush;

    // Join a group for the RADIO-DISH pattern. Call only on ZMQ_DISH.
    // Returns 0 if OK, -1 if failed.
    function Join(const Group: string): Integer;

    // Leave a group for the RADIO-DISH pattern. Call only on ZMQ_DISH.
    // Returns 0 if OK, -1 if failed.
    function Leave(const Group: string): Integer;

    // Check whether the socket has available message to read.
    function HasIn: Boolean;

    // Get socket option `router_notify`.
    // Available from libzmq 4.3.0.
    function RouterNotify: Integer;

    // Set socket option `router_notify`.
    // Available from libzmq 4.3.0.
    procedure SetRouterNotify(RouterNotify: Integer);

    // Get socket option `multicast_loop`.
    // Available from libzmq 4.3.0.
    function MulticastLoop: Integer;

    // Set socket option `multicast_loop`.
    // Available from libzmq 4.3.0.
    procedure SetMulticastLoop(MulticastLoop: Integer);

    // Get socket option `metadata`.
    // Available from libzmq 4.3.0.
    function Metadata: string;

    // Set socket option `metadata`.
    // Available from libzmq 4.3.0.
    procedure SetMetadata(const Metadata: string);

    // Get socket option `loopback_fastpath`.
    // Available from libzmq 4.3.0.
    function LoopbackFastpath: Integer;

    // Set socket option `loopback_fastpath`.
    // Available from libzmq 4.3.0.
    procedure SetLoopbackFastpath(LoopbackFastpath: Integer);

    // Get socket option `zap_enforce_domain`.
    // Available from libzmq 4.3.0.
    function ZapEnforceDomain: Integer;

    // Set socket option `zap_enforce_domain`.
    // Available from libzmq 4.3.0.
    procedure SetZapEnforceDomain(ZapEnforceDomain: Integer);

    // Get socket option `gssapi_principal_nametype`.
    // Available from libzmq 4.3.0.
    function GssapiPrincipalNametype: Integer;

    // Set socket option `gssapi_principal_nametype`.
    // Available from libzmq 4.3.0.
    procedure SetGssapiPrincipalNametype(GssapiPrincipalNametype: Integer);

    // Get socket option `gssapi_service_principal_nametype`.
    // Available from libzmq 4.3.0.
    function GssapiServicePrincipalNametype: Integer;

    // Set socket option `gssapi_service_principal_nametype`.
    // Available from libzmq 4.3.0.
    procedure SetGssapiServicePrincipalNametype(GssapiServicePrincipalNametype: Integer);

    // Get socket option `bindtodevice`.
    // Available from libzmq 4.3.0.
    function Bindtodevice: string;

    // Set socket option `bindtodevice`.
    // Available from libzmq 4.3.0.
    procedure SetBindtodevice(const Bindtodevice: string);

    // Get socket option `heartbeat_ivl`.
    // Available from libzmq 4.2.0.
    function HeartbeatIvl: Integer;

    // Set socket option `heartbeat_ivl`.
    // Available from libzmq 4.2.0.
    procedure SetHeartbeatIvl(HeartbeatIvl: Integer);

    // Get socket option `heartbeat_ttl`.
    // Available from libzmq 4.2.0.
    function HeartbeatTtl: Integer;

    // Set socket option `heartbeat_ttl`.
    // Available from libzmq 4.2.0.
    procedure SetHeartbeatTtl(HeartbeatTtl: Integer);

    // Get socket option `heartbeat_timeout`.
    // Available from libzmq 4.2.0.
    function HeartbeatTimeout: Integer;

    // Set socket option `heartbeat_timeout`.
    // Available from libzmq 4.2.0.
    procedure SetHeartbeatTimeout(HeartbeatTimeout: Integer);

    // Get socket option `use_fd`.
    // Available from libzmq 4.2.0.
    function UseFd: Integer;

    // Set socket option `use_fd`.
    // Available from libzmq 4.2.0.
    procedure SetUseFd(UseFd: Integer);

    // Set socket option `xpub_manual`.
    // Available from libzmq 4.2.0.
    procedure SetXpubManual(XpubManual: Integer);

    // Set socket option `xpub_welcome_msg`.
    // Available from libzmq 4.2.0.
    procedure SetXpubWelcomeMsg(const XpubWelcomeMsg: string);

    // Set socket option `stream_notify`.
    // Available from libzmq 4.2.0.
    procedure SetStreamNotify(StreamNotify: Integer);

    // Get socket option `invert_matching`.
    // Available from libzmq 4.2.0.
    function InvertMatching: Integer;

    // Set socket option `invert_matching`.
    // Available from libzmq 4.2.0.
    procedure SetInvertMatching(InvertMatching: Integer);

    // Set socket option `xpub_verboser`.
    // Available from libzmq 4.2.0.
    procedure SetXpubVerboser(XpubVerboser: Integer);

    // Get socket option `connect_timeout`.
    // Available from libzmq 4.2.0.
    function ConnectTimeout: Integer;

    // Set socket option `connect_timeout`.
    // Available from libzmq 4.2.0.
    procedure SetConnectTimeout(ConnectTimeout: Integer);

    // Get socket option `tcp_maxrt`.
    // Available from libzmq 4.2.0.
    function TcpMaxrt: Integer;

    // Set socket option `tcp_maxrt`.
    // Available from libzmq 4.2.0.
    procedure SetTcpMaxrt(TcpMaxrt: Integer);

    // Get socket option `thread_safe`.
    // Available from libzmq 4.2.0.
    function ThreadSafe: Integer;

    // Get socket option `multicast_maxtpdu`.
    // Available from libzmq 4.2.0.
    function MulticastMaxtpdu: Integer;

    // Set socket option `multicast_maxtpdu`.
    // Available from libzmq 4.2.0.
    procedure SetMulticastMaxtpdu(MulticastMaxtpdu: Integer);

    // Get socket option `vmci_buffer_size`.
    // Available from libzmq 4.2.0.
    function VmciBufferSize: Integer;

    // Set socket option `vmci_buffer_size`.
    // Available from libzmq 4.2.0.
    procedure SetVmciBufferSize(VmciBufferSize: Integer);

    // Get socket option `vmci_buffer_min_size`.
    // Available from libzmq 4.2.0.
    function VmciBufferMinSize: Integer;

    // Set socket option `vmci_buffer_min_size`.
    // Available from libzmq 4.2.0.
    procedure SetVmciBufferMinSize(VmciBufferMinSize: Integer);

    // Get socket option `vmci_buffer_max_size`.
    // Available from libzmq 4.2.0.
    function VmciBufferMaxSize: Integer;

    // Set socket option `vmci_buffer_max_size`.
    // Available from libzmq 4.2.0.
    procedure SetVmciBufferMaxSize(VmciBufferMaxSize: Integer);

    // Get socket option `vmci_connect_timeout`.
    // Available from libzmq 4.2.0.
    function VmciConnectTimeout: Integer;

    // Set socket option `vmci_connect_timeout`.
    // Available from libzmq 4.2.0.
    procedure SetVmciConnectTimeout(VmciConnectTimeout: Integer);

    // Get socket option `tos`.
    // Available from libzmq 4.1.0.
    function Tos: Integer;

    // Set socket option `tos`.
    // Available from libzmq 4.1.0.
    procedure SetTos(Tos: Integer);

    // Set socket option `router_handover`.
    // Available from libzmq 4.1.0.
    procedure SetRouterHandover(RouterHandover: Integer);

    // Set socket option `connect_rid`.
    // Available from libzmq 4.1.0.
    procedure SetConnectRid(const ConnectRid: string);

    // Set socket option `connect_rid` from 32-octet binary
    // Available from libzmq 4.1.0.
    procedure SetConnectRidBin(ConnectRid: PByte);

    // Get socket option `handshake_ivl`.
    // Available from libzmq 4.1.0.
    function HandshakeIvl: Integer;

    // Set socket option `handshake_ivl`.
    // Available from libzmq 4.1.0.
    procedure SetHandshakeIvl(HandshakeIvl: Integer);

    // Get socket option `socks_proxy`.
    // Available from libzmq 4.1.0.
    function SocksProxy: string;

    // Set socket option `socks_proxy`.
    // Available from libzmq 4.1.0.
    procedure SetSocksProxy(const SocksProxy: string);

    // Set socket option `xpub_nodrop`.
    // Available from libzmq 4.1.0.
    procedure SetXpubNodrop(XpubNodrop: Integer);

    // Set socket option `router_mandatory`.
    // Available from libzmq 4.0.0.
    procedure SetRouterMandatory(RouterMandatory: Integer);

    // Set socket option `probe_router`.
    // Available from libzmq 4.0.0.
    procedure SetProbeRouter(ProbeRouter: Integer);

    // Set socket option `req_relaxed`.
    // Available from libzmq 4.0.0.
    procedure SetReqRelaxed(ReqRelaxed: Integer);

    // Set socket option `req_correlate`.
    // Available from libzmq 4.0.0.
    procedure SetReqCorrelate(ReqCorrelate: Integer);

    // Set socket option `conflate`.
    // Available from libzmq 4.0.0.
    procedure SetConflate(Conflate: Integer);

    // Get socket option `zap_domain`.
    // Available from libzmq 4.0.0.
    function ZapDomain: string;

    // Set socket option `zap_domain`.
    // Available from libzmq 4.0.0.
    procedure SetZapDomain(const ZapDomain: string);

    // Get socket option `mechanism`.
    // Available from libzmq 4.0.0.
    function Mechanism: Integer;

    // Get socket option `plain_server`.
    // Available from libzmq 4.0.0.
    function PlainServer: Integer;

    // Set socket option `plain_server`.
    // Available from libzmq 4.0.0.
    procedure SetPlainServer(PlainServer: Integer);

    // Get socket option `plain_username`.
    // Available from libzmq 4.0.0.
    function PlainUsername: string;

    // Set socket option `plain_username`.
    // Available from libzmq 4.0.0.
    procedure SetPlainUsername(const PlainUsername: string);

    // Get socket option `plain_password`.
    // Available from libzmq 4.0.0.
    function PlainPassword: string;

    // Set socket option `plain_password`.
    // Available from libzmq 4.0.0.
    procedure SetPlainPassword(const PlainPassword: string);

    // Get socket option `curve_server`.
    // Available from libzmq 4.0.0.
    function CurveServer: Integer;

    // Set socket option `curve_server`.
    // Available from libzmq 4.0.0.
    procedure SetCurveServer(CurveServer: Integer);

    // Get socket option `curve_publickey`.
    // Available from libzmq 4.0.0.
    function CurvePublickey: string;

    // Set socket option `curve_publickey`.
    // Available from libzmq 4.0.0.
    procedure SetCurvePublickey(const CurvePublickey: string);

    // Set socket option `curve_publickey` from 32-octet binary
    // Available from libzmq 4.0.0.
    procedure SetCurvePublickeyBin(CurvePublickey: PByte);

    // Get socket option `curve_secretkey`.
    // Available from libzmq 4.0.0.
    function CurveSecretkey: string;

    // Set socket option `curve_secretkey`.
    // Available from libzmq 4.0.0.
    procedure SetCurveSecretkey(const CurveSecretkey: string);

    // Set socket option `curve_secretkey` from 32-octet binary
    // Available from libzmq 4.0.0.
    procedure SetCurveSecretkeyBin(CurveSecretkey: PByte);

    // Get socket option `curve_serverkey`.
    // Available from libzmq 4.0.0.
    function CurveServerkey: string;

    // Set socket option `curve_serverkey`.
    // Available from libzmq 4.0.0.
    procedure SetCurveServerkey(const CurveServerkey: string);

    // Set socket option `curve_serverkey` from 32-octet binary
    // Available from libzmq 4.0.0.
    procedure SetCurveServerkeyBin(CurveServerkey: PByte);

    // Get socket option `gssapi_server`.
    // Available from libzmq 4.0.0.
    function GssapiServer: Integer;

    // Set socket option `gssapi_server`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiServer(GssapiServer: Integer);

    // Get socket option `gssapi_plaintext`.
    // Available from libzmq 4.0.0.
    function GssapiPlaintext: Integer;

    // Set socket option `gssapi_plaintext`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiPlaintext(GssapiPlaintext: Integer);

    // Get socket option `gssapi_principal`.
    // Available from libzmq 4.0.0.
    function GssapiPrincipal: string;

    // Set socket option `gssapi_principal`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiPrincipal(const GssapiPrincipal: string);

    // Get socket option `gssapi_service_principal`.
    // Available from libzmq 4.0.0.
    function GssapiServicePrincipal: string;

    // Set socket option `gssapi_service_principal`.
    // Available from libzmq 4.0.0.
    procedure SetGssapiServicePrincipal(const GssapiServicePrincipal: string);

    // Get socket option `ipv6`.
    // Available from libzmq 4.0.0.
    function Ipv6: Integer;

    // Set socket option `ipv6`.
    // Available from libzmq 4.0.0.
    procedure SetIpv6(Ipv6: Integer);

    // Get socket option `immediate`.
    // Available from libzmq 4.0.0.
    function Immediate: Integer;

    // Set socket option `immediate`.
    // Available from libzmq 4.0.0.
    procedure SetImmediate(Immediate: Integer);

    // Get socket option `sndhwm`.
    // Available from libzmq 3.0.0.
    function Sndhwm: Integer;

    // Set socket option `sndhwm`.
    // Available from libzmq 3.0.0.
    procedure SetSndhwm(Sndhwm: Integer);

    // Get socket option `rcvhwm`.
    // Available from libzmq 3.0.0.
    function Rcvhwm: Integer;

    // Set socket option `rcvhwm`.
    // Available from libzmq 3.0.0.
    procedure SetRcvhwm(Rcvhwm: Integer);

    // Get socket option `maxmsgsize`.
    // Available from libzmq 3.0.0.
    function Maxmsgsize: Integer;

    // Set socket option `maxmsgsize`.
    // Available from libzmq 3.0.0.
    procedure SetMaxmsgsize(Maxmsgsize: Integer);

    // Get socket option `multicast_hops`.
    // Available from libzmq 3.0.0.
    function MulticastHops: Integer;

    // Set socket option `multicast_hops`.
    // Available from libzmq 3.0.0.
    procedure SetMulticastHops(MulticastHops: Integer);

    // Set socket option `xpub_verbose`.
    // Available from libzmq 3.0.0.
    procedure SetXpubVerbose(XpubVerbose: Integer);

    // Get socket option `tcp_keepalive`.
    // Available from libzmq 3.0.0.
    function TcpKeepalive: Integer;

    // Set socket option `tcp_keepalive`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepalive(TcpKeepalive: Integer);

    // Get socket option `tcp_keepalive_idle`.
    // Available from libzmq 3.0.0.
    function TcpKeepaliveIdle: Integer;

    // Set socket option `tcp_keepalive_idle`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepaliveIdle(TcpKeepaliveIdle: Integer);

    // Get socket option `tcp_keepalive_cnt`.
    // Available from libzmq 3.0.0.
    function TcpKeepaliveCnt: Integer;

    // Set socket option `tcp_keepalive_cnt`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepaliveCnt(TcpKeepaliveCnt: Integer);

    // Get socket option `tcp_keepalive_intvl`.
    // Available from libzmq 3.0.0.
    function TcpKeepaliveIntvl: Integer;

    // Set socket option `tcp_keepalive_intvl`.
    // Available from libzmq 3.0.0.
    procedure SetTcpKeepaliveIntvl(TcpKeepaliveIntvl: Integer);

    // Get socket option `tcp_accept_filter`.
    // Available from libzmq 3.0.0.
    function TcpAcceptFilter: string;

    // Set socket option `tcp_accept_filter`.
    // Available from libzmq 3.0.0.
    procedure SetTcpAcceptFilter(const TcpAcceptFilter: string);

    // Get socket option `last_endpoint`.
    // Available from libzmq 3.0.0.
    function LastEndpoint: string;

    // Set socket option `router_raw`.
    // Available from libzmq 3.0.0.
    procedure SetRouterRaw(RouterRaw: Integer);

    // Get socket option `ipv4only`.
    // Available from libzmq 3.0.0.
    function Ipv4only: Integer;

    // Set socket option `ipv4only`.
    // Available from libzmq 3.0.0.
    procedure SetIpv4only(Ipv4only: Integer);

    // Set socket option `delay_attach_on_connect`.
    // Available from libzmq 3.0.0.
    procedure SetDelayAttachOnConnect(DelayAttachOnConnect: Integer);

    // Get socket option `hwm`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function Hwm: Integer;

    // Set socket option `hwm`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetHwm(Hwm: Integer);

    // Get socket option `swap`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function Swap: Integer;

    // Set socket option `swap`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetSwap(Swap: Integer);

    // Get socket option `affinity`.
    // Available from libzmq 2.0.0.
    function Affinity: Integer;

    // Set socket option `affinity`.
    // Available from libzmq 2.0.0.
    procedure SetAffinity(Affinity: Integer);

    // Get socket option `identity`.
    // Available from libzmq 2.0.0.
    function Identity: string;

    // Set socket option `identity`.
    // Available from libzmq 2.0.0.
    procedure SetIdentity(const Identity: string);

    // Get socket option `rate`.
    // Available from libzmq 2.0.0.
    function Rate: Integer;

    // Set socket option `rate`.
    // Available from libzmq 2.0.0.
    procedure SetRate(Rate: Integer);

    // Get socket option `recovery_ivl`.
    // Available from libzmq 2.0.0.
    function RecoveryIvl: Integer;

    // Set socket option `recovery_ivl`.
    // Available from libzmq 2.0.0.
    procedure SetRecoveryIvl(RecoveryIvl: Integer);

    // Get socket option `recovery_ivl_msec`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function RecoveryIvlMsec: Integer;

    // Set socket option `recovery_ivl_msec`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetRecoveryIvlMsec(RecoveryIvlMsec: Integer);

    // Get socket option `mcast_loop`.
    // Available from libzmq 2.0.0 to 3.0.0.
    function McastLoop: Integer;

    // Set socket option `mcast_loop`.
    // Available from libzmq 2.0.0 to 3.0.0.
    procedure SetMcastLoop(McastLoop: Integer);

    // Get socket option `rcvtimeo`.
    // Available from libzmq 2.2.0.
    function Rcvtimeo: Integer;

    // Set socket option `rcvtimeo`.
    // Available from libzmq 2.2.0.
    procedure SetRcvtimeo(Rcvtimeo: Integer);

    // Get socket option `sndtimeo`.
    // Available from libzmq 2.2.0.
    function Sndtimeo: Integer;

    // Set socket option `sndtimeo`.
    // Available from libzmq 2.2.0.
    procedure SetSndtimeo(Sndtimeo: Integer);

    // Get socket option `sndbuf`.
    // Available from libzmq 2.0.0.
    function Sndbuf: Integer;

    // Set socket option `sndbuf`.
    // Available from libzmq 2.0.0.
    procedure SetSndbuf(Sndbuf: Integer);

    // Get socket option `rcvbuf`.
    // Available from libzmq 2.0.0.
    function Rcvbuf: Integer;

    // Set socket option `rcvbuf`.
    // Available from libzmq 2.0.0.
    procedure SetRcvbuf(Rcvbuf: Integer);

    // Get socket option `linger`.
    // Available from libzmq 2.0.0.
    function Linger: Integer;

    // Set socket option `linger`.
    // Available from libzmq 2.0.0.
    procedure SetLinger(Linger: Integer);

    // Get socket option `reconnect_ivl`.
    // Available from libzmq 2.0.0.
    function ReconnectIvl: Integer;

    // Set socket option `reconnect_ivl`.
    // Available from libzmq 2.0.0.
    procedure SetReconnectIvl(ReconnectIvl: Integer);

    // Get socket option `reconnect_ivl_max`.
    // Available from libzmq 2.0.0.
    function ReconnectIvlMax: Integer;

    // Set socket option `reconnect_ivl_max`.
    // Available from libzmq 2.0.0.
    procedure SetReconnectIvlMax(ReconnectIvlMax: Integer);

    // Get socket option `backlog`.
    // Available from libzmq 2.0.0.
    function Backlog: Integer;

    // Set socket option `backlog`.
    // Available from libzmq 2.0.0.
    procedure SetBacklog(Backlog: Integer);

    // Set socket option `subscribe`.
    // Available from libzmq 2.0.0.
    procedure SetSubscribe(const Subscribe: string);

    // Set socket option `unsubscribe`.
    // Available from libzmq 2.0.0.
    procedure SetUnsubscribe(const Unsubscribe: string);

    // Get socket option `type`.
    // Available from libzmq 2.0.0.
    function &Type: Integer;

    // Get socket option `rcvmore`.
    // Available from libzmq 2.0.0.
    function Rcvmore: Integer;

    // Get socket option `fd`.
    // Available from libzmq 2.0.0.
    function Fd: TSocket;

    // Get socket option `events`.
    // Available from libzmq 2.0.0.
    function Events: Integer;
  end;

  // sending and receiving strings
  TZstr = class
  public

    // Receive C string from socket. Caller must free returned string using
    // zstr_free(). Returns NULL if the context is being terminated or the
    // process was interrupted.
    class function Recv(const Source: IZSock): string;

    // De-compress and receive C string from socket, received as a message
    // with two frames: size of the uncompressed string, and the string itself.
    // Caller must free returned string using zstr_free(). Returns NULL if the
    // context is being terminated or the process was interrupted.
    class function RecvCompress(const Source: IZSock): string;

    // Send a C string to a socket, as a frame. The string is sent without
    // trailing null byte; to read this you can use zstr_recv, or a similar
    // method that adds a null terminator on the received string. String
    // may be NULL, which is sent as "".
    class function Send(const Dest: IZSock; const &String: string): Integer;

    // Send a C string to a socket, as zstr_send(), with a MORE flag, so that
    // you can send further strings in the same multi-part message.
    class function Sendm(const Dest: IZSock; const &String: string): Integer;

    // Send a formatted string to a socket. Note that you should NOT use
    // user-supplied strings in the format (they may contain '%' which
    // will create security holes).
    class function Sendf(const Dest: IZSock; const Format: string): Integer;

    // Send a formatted string to a socket, as for zstr_sendf(), with a
    // MORE flag, so that you can send further strings in the same multi-part
    // message.
    class function Sendfm(const Dest: IZSock; const Format: string): Integer;

    // Send a series of strings (until NULL) as multipart data
    // Returns 0 if the strings could be sent OK, or -1 on error.
    class function Sendx(const Dest: IZSock; const &String: string): Integer;

    // Compress and send a C string to a socket, as a message with two frames:
    // size of the uncompressed string, and the string itself. The string is
    // sent without trailing null byte; to read this you can use
    // zstr_recv_compress, or a similar method that de-compresses and adds a
    // null terminator on the received string.
    class function SendCompress(const Dest: IZSock; const &String: string): Integer;

    // Compress and send a C string to a socket, as zstr_send_compress(),
    // with a MORE flag, so that you can send further strings in the same
    // multi-part message.
    class function SendmCompress(const Dest: IZSock; const &String: string): Integer;

    // Accepts a void pointer and returns a fresh character string. If source
    // is null, returns an empty string.
    class function Str(const Source: IZSock): string;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  //
  TZsys = class
  public

    // Initialize CZMQ zsys layer; this happens automatically when you create
    // a socket or an actor; however this call lets you force initialization
    // earlier, so e.g. logging is properly set-up before you start working.
    // Not threadsafe, so call only from main thread. Safe to call multiple
    // times. Returns global CZMQ context.
    class function Init: Pointer;

    // Optionally shut down the CZMQ zsys layer; this normally happens automatically
    // when the process exits; however this call lets you force a shutdown
    // earlier, avoiding any potential problems with atexit() ordering, especially
    // with Windows dlls.
    class procedure Shutdown;

    // Get a new ZMQ socket, automagically creating a ZMQ context if this is
    // the first time. Caller is responsible for destroying the ZMQ socket
    // before process exits, to avoid a ZMQ deadlock. Note: you should not use
    // this method in CZMQ apps, use zsock_new() instead.
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function Socket(&Type: Integer; const Filename: string; LineNbr: NativeUInt): Pointer;

    // Destroy/close a ZMQ socket. You should call this for every socket you
    // create using zsys_socket().
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function Close(Handle: Pointer; const Filename: string; LineNbr: NativeUInt): Integer;

    // Return ZMQ socket name for socket type
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function Sockname(Socktype: Integer): string;

    // Create a pipe, which consists of two PAIR sockets connected over inproc.
    // The pipe is configured to use the zsys_pipehwm setting. Returns the
    // frontend socket successful, NULL if failed.
    class function CreatePipe(var BackendP: IZsock): IZsock;

    // Set interrupt handler; this saves the default handlers so that a
    // zsys_handler_reset () can restore them. If you call this multiple times
    // then the last handler will take affect. If handler_fn is NULL, disables
    // default SIGINT/SIGTERM handling in CZMQ.
    class procedure HandlerSet(HandlerFn: PZsysHandlerFn);

    // Reset interrupt handler, call this at exit if needed
    class procedure HandlerReset;

    // Set default interrupt handler, so Ctrl-C or SIGTERM will set
    // zsys_interrupted. Idempotent; safe to call multiple times.
    // Can be suppressed by ZSYS_SIGHANDLER=false
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class procedure CatchInterrupts;

    // Check if default interrupt handler of Ctrl-C or SIGTERM was called.
    // Does not work if ZSYS_SIGHANDLER is false and code does not call
    // set interrupted on signal.
    class function IsInterrupted: Boolean;

    // Set interrupted flag. This is done by default signal handler, however
    // this can be handy for language bindings or cases without default
    // signal handler.
    class procedure SetInterrupted;

    // Return 1 if file exists, else zero
    class function FileExists(const Filename: string): Boolean;

    // Return file modification time. Returns 0 if the file does not exist.
    class function FileModified(const Filename: string): Int64;

    // Return file mode; provides at least support for the POSIX S_ISREG(m)
    // and S_ISDIR(m) macros and the S_IRUSR and S_IWUSR bits, on all boxes.
    // Returns a mode_t cast to int, or -1 in case of error.
    class function FileMode(const Filename: string): Integer;

    // Delete file. Does not complain if the file is absent
    class function FileDelete(const Filename: string): Integer;

    // Check if file is 'stable'
    class function FileStable(const Filename: string): Boolean;

    // Create a file path if it doesn't exist. The file path is treated as
    // printf format.
    class function DirCreate(const Pathname: string): Integer;

    // Remove a file path if empty; the pathname is treated as printf format.
    class function DirDelete(const Pathname: string): Integer;

    // Move to a specified working directory. Returns 0 if OK, -1 if this failed.
    class function DirChange(const Pathname: string): Integer;

    // Set private file creation mode; all files created from here will be
    // readable/writable by the owner only.
    class procedure FileModePrivate;

    // Reset default file creation mode; all files created from here will use
    // process file mode defaults.
    class procedure FileModeDefault;

    // Return the CZMQ version for run-time API detection; returns version
    // number into provided fields, providing reference isn't null in each case.
    class procedure Version(var Major: Integer; var Minor: Integer; var Patch: Integer);

    // Format a string using printf formatting, returning a freshly allocated
    // buffer. If there was insufficient memory, returns NULL. Free the returned
    // string using zstr_free(). The hinted version allows to optimize by using
    // a larger starting buffer size (known to/assumed by the developer) and so
    // avoid reallocations.
    class function SprintfHint(Hint: Integer; const Format: string): string;

    // Format a string using printf formatting, returning a freshly allocated
    // buffer. If there was insufficient memory, returns NULL. Free the returned
    // string using zstr_free().
    class function Sprintf(const Format: string): string;

    // Format a string with a va_list argument, returning a freshly allocated
    // buffer. If there was insufficient memory, returns NULL. Free the returned
    // string using zstr_free().
    class function Vprintf(const Format: string; Argptr: va_list): string;

    // Create UDP beacon socket; if the routable option is true, uses
    // multicast (not yet implemented), else uses broadcast. This method
    // and related ones might _eventually_ be moved to a zudp class.
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function UdpNew(Routable: Boolean): TSocket;

    // Close a UDP socket
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function UdpClose(Handle: TSocket): Integer;

    // Send zframe to UDP socket, return -1 if sending failed due to
    // interface having disappeared (happens easily with WiFi)
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function UdpSend(Udpsock: TSocket; const Frame: IZframe; Address: Pointer; Addrlen: Integer): Integer;

    // Receive zframe from UDP socket, and set address of peer that sent it
    // The peername must be a char [INET_ADDRSTRLEN] array if IPv6 is disabled or
    // NI_MAXHOST if it's enabled. Returns NULL when failing to get peer address.
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class function UdpRecv(Udpsock: TSocket; const Peername: string; Peerlen: Integer): IZframe;

    // Handle an I/O error on some socket operation; will report and die on
    // fatal errors, and continue silently on "try again" errors.
    // *** This is for CZMQ internal use only and may change arbitrarily ***
    class procedure SocketError(const Reason: string);

    // Return current host name, for use in public tcp:// endpoints. Caller gets
    // a freshly allocated string, should free it using zstr_free(). If the host
    // name is not resolvable, returns NULL.
    class function Hostname: string;

    // Move the current process into the background. The precise effect depends
    // on the operating system. On POSIX boxes, moves to a specified working
    // directory (if specified), closes all file handles, reopens stdin, stdout,
    // and stderr to the null device, and sets the process to ignore SIGHUP. On
    // Windows, does nothing. Returns 0 if OK, -1 if there was an error.
    class function Daemonize(const Workdir: string): Integer;

    // Drop the process ID into the lockfile, with exclusive lock, and switch
    // the process to the specified group and/or user. Any of the arguments
    // may be null, indicating a no-op. Returns 0 on success, -1 on failure.
    // Note if you combine this with zsys_daemonize, run after, not before
    // that method, or the lockfile will hold the wrong process ID.
    class function RunAs(const Lockfile: string; const Group: string; const User: string): Integer;

    // Returns true if the underlying libzmq supports CURVE security.
    // Uses a heuristic probe according to the version of libzmq being used.
    class function HasCurve: Boolean;

    // Configure the number of I/O threads that ZeroMQ will use. A good
    // rule of thumb is one thread per gigabit of traffic in or out. The
    // default is 1, sufficient for most applications. If the environment
    // variable ZSYS_IO_THREADS is defined, that provides the default.
    // Note that this method is valid only before any socket is created.
    class procedure SetIoThreads(IoThreads: NativeUInt);

    // Configure the scheduling policy of the ZMQ context thread pool.
    // Not available on Windows. See the sched_setscheduler man page or sched.h
    // for more information. If the environment variable ZSYS_THREAD_SCHED_POLICY
    // is defined, that provides the default.
    // Note that this method is valid only before any socket is created.
    class procedure SetThreadSchedPolicy(Policy: Integer);

    // Configure the scheduling priority of the ZMQ context thread pool.
    // Not available on Windows. See the sched_setscheduler man page or sched.h
    // for more information. If the environment variable ZSYS_THREAD_PRIORITY is
    // defined, that provides the default.
    // Note that this method is valid only before any socket is created.
    class procedure SetThreadPriority(Priority: Integer);

    // Configure the numeric prefix to each thread created for the internal
    // context's thread pool. This option is only supported on Linux.
    // If the environment variable ZSYS_THREAD_NAME_PREFIX is defined, that
    // provides the default.
    // Note that this method is valid only before any socket is created.
    class procedure SetThreadNamePrefix(Prefix: Integer);

    // Return thread name prefix.
    class function ThreadNamePrefix: Integer;

    // Adds a specific CPU to the affinity list of the ZMQ context thread pool.
    // This option is only supported on Linux.
    // Note that this method is valid only before any socket is created.
    class procedure ThreadAffinityCpuAdd(Cpu: Integer);

    // Removes a specific CPU to the affinity list of the ZMQ context thread pool.
    // This option is only supported on Linux.
    // Note that this method is valid only before any socket is created.
    class procedure ThreadAffinityCpuRemove(Cpu: Integer);

    // Configure the number of sockets that ZeroMQ will allow. The default
    // is 1024. The actual limit depends on the system, and you can query it
    // by using zsys_socket_limit (). A value of zero means "maximum".
    // Note that this method is valid only before any socket is created.
    class procedure SetMaxSockets(MaxSockets: NativeUInt);

    // Return maximum number of ZeroMQ sockets that the system will support.
    class function SocketLimit: NativeUInt;

    // Configure the maximum allowed size of a message sent.
    // The default is INT_MAX.
    class procedure SetMaxMsgsz(MaxMsgsz: Integer);

    // Return maximum message size.
    class function MaxMsgsz: Integer;

    // Configure whether to use zero copy strategy in libzmq. If the environment
    // variable ZSYS_ZERO_COPY_RECV is defined, that provides the default.
    // Otherwise the default is 1.
    class procedure SetZeroCopyRecv(ZeroCopy: Integer);

    // Return ZMQ_ZERO_COPY_RECV option.
    class function ZeroCopyRecv: Integer;

    // Configure the threshold value of filesystem object age per st_mtime
    // that should elapse until we consider that object "stable" at the
    // current zclock_time() moment.
    // The default is S_DEFAULT_ZSYS_FILE_STABLE_AGE_MSEC defined in zsys.c
    // which generally depends on host OS, with fallback value of 5000.
    class procedure SetFileStableAgeMsec(FileStableAgeMsec: Int64);

    // Return current threshold value of file stable age in msec.
    // This can be used in code that chooses to wait for this timeout
    // before testing if a filesystem object is "stable" or not.
    class function FileStableAgeMsec: Int64;

    // Configure the default linger timeout in msecs for new zsock instances.
    // You can also set this separately on each zsock_t instance. The default
    // linger time is zero, i.e. any pending messages will be dropped. If the
    // environment variable ZSYS_LINGER is defined, that provides the default.
    // Note that process exit will typically be delayed by the linger time.
    class procedure SetLinger(Linger: NativeUInt);

    // Configure the default outgoing pipe limit (HWM) for new zsock instances.
    // You can also set this separately on each zsock_t instance. The default
    // HWM is 1,000, on all versions of ZeroMQ. If the environment variable
    // ZSYS_SNDHWM is defined, that provides the default. Note that a value of
    // zero means no limit, i.e. infinite memory consumption.
    class procedure SetSndhwm(Sndhwm: NativeUInt);

    // Configure the default incoming pipe limit (HWM) for new zsock instances.
    // You can also set this separately on each zsock_t instance. The default
    // HWM is 1,000, on all versions of ZeroMQ. If the environment variable
    // ZSYS_RCVHWM is defined, that provides the default. Note that a value of
    // zero means no limit, i.e. infinite memory consumption.
    class procedure SetRcvhwm(Rcvhwm: NativeUInt);

    // Configure the default HWM for zactor internal pipes; this is set on both
    // ends of the pipe, for outgoing messages only (sndhwm). The default HWM is
    // 1,000, on all versions of ZeroMQ. If the environment var ZSYS_ACTORHWM is
    // defined, that provides the default. Note that a value of zero means no
    // limit, i.e. infinite memory consumption.
    class procedure SetPipehwm(Pipehwm: NativeUInt);

    // Return the HWM for zactor internal pipes.
    class function Pipehwm: NativeUInt;

    // Configure use of IPv6 for new zsock instances. By default sockets accept
    // and make only IPv4 connections. When you enable IPv6, sockets will accept
    // and connect to both IPv4 and IPv6 peers. You can override the setting on
    // each zsock_t instance. The default is IPv4 only (ipv6 set to 0). If the
    // environment variable ZSYS_IPV6 is defined (as 1 or 0), this provides the
    // default. Note: has no effect on ZMQ v2.
    class procedure SetIpv6(Ipv6: Integer);

    // Return use of IPv6 for zsock instances.
    class function Ipv6: Integer;

    // Set network interface name to use for broadcasts, particularly zbeacon.
    // This lets the interface be configured for test environments where required.
    // For example, on Mac OS X, zbeacon cannot bind to 255.255.255.255 which is
    // the default when there is no specified interface. If the environment
    // variable ZSYS_INTERFACE is set, use that as the default interface name.
    // Setting the interface to "*" means "use all available interfaces".
    class procedure SetInterface(const Value: string);

    // Return network interface to use for broadcasts, or "" if none was set.
    class function &Interface: string;

    // Set IPv6 address to use zbeacon socket, particularly for receiving zbeacon.
    // This needs to be set IPv6 is enabled as IPv6 can have multiple addresses
    // on a given interface. If the environment variable ZSYS_IPV6_ADDRESS is set,
    // use that as the default IPv6 address.
    class procedure SetIpv6Address(const Value: string);

    // Return IPv6 address to use for zbeacon reception, or "" if none was set.
    class function Ipv6Address: string;

    // Set IPv6 milticast address to use for sending zbeacon messages. This needs
    // to be set if IPv6 is enabled. If the environment variable
    // ZSYS_IPV6_MCAST_ADDRESS is set, use that as the default IPv6 multicast
    // address.
    class procedure SetIpv6McastAddress(const Value: string);

    // Return IPv6 multicast address to use for sending zbeacon, or "" if none was
    // set.
    class function Ipv6McastAddress: string;

    // Configure the automatic use of pre-allocated FDs when creating new sockets.
    // If 0 (default), nothing will happen. Else, when a new socket is bound, the
    // system API will be used to check if an existing pre-allocated FD with a
    // matching port (if TCP) or path (if IPC) exists, and if it does it will be
    // set via the ZMQ_USE_FD socket option so that the library will use it
    // instead of creating a new socket.
    class procedure SetAutoUseFd(AutoUseFd: Integer);

    // Return use of automatic pre-allocated FDs for zsock instances.
    class function AutoUseFd: Integer;

    // Print formatted string. Format is specified by variable names
    // in Python-like format style
    //
    // "%(KEY)s=%(VALUE)s", KEY=key, VALUE=value
    // become
    // "key=value"
    //
    // Returns freshly allocated string or NULL in a case of error.
    // Not enough memory, invalid format specifier, name not in args
    class function Zprintf(const Format: string; const Args: IZhash): string;

    // Return error string for given format/args combination.
    class function ZprintfError(const Format: string; const Args: IZhash): string;

    // Print formatted string. Format is specified by variable names
    // in Python-like format style
    //
    // "%(KEY)s=%(VALUE)s", KEY=key, VALUE=value
    // become
    // "key=value"
    //
    // Returns freshly allocated string or NULL in a case of error.
    // Not enough memory, invalid format specifier, name not in args
    class function Zplprintf(const Format: string; const Args: IZconfig): string;

    // Return error string for given format/args combination.
    class function ZplprintfError(const Format: string; const Args: IZconfig): string;

    // Set log identity, which is a string that prefixes all log messages sent
    // by this process. The log identity defaults to the environment variable
    // ZSYS_LOGIDENT, if that is set.
    class procedure SetLogident(const Value: string);

    // Set stream to receive log traffic. By default, log traffic is sent to
    // stdout. If you set the stream to NULL, no stream will receive the log
    // traffic (it may still be sent to the system facility).
    class procedure SetLogstream(Stream: Pointer);

    // Sends log output to a PUB socket bound to the specified endpoint. To
    // collect such log output, create a SUB socket, subscribe to the traffic
    // you care about, and connect to the endpoint. Log traffic is sent as a
    // single string frame, in the same format as when sent to stdout. The
    // log system supports a single sender; multiple calls to this method will
    // bind the same sender to multiple endpoints. To disable the sender, call
    // this method with a null argument.
    class procedure SetLogsender(const Endpoint: string);

    // Enable or disable logging to the system facility (syslog on POSIX boxes,
    // event log on Windows). By default this is disabled.
    class procedure SetLogsystem(Logsystem: Boolean);

    // Log error condition - highest priority
    class procedure Error(const Format: string);

    // Log warning condition - high priority
    class procedure Warning(const Format: string);

    // Log normal, but significant, condition - normal priority
    class procedure Notice(const Format: string);

    // Log informational message - low priority
    class procedure Info(const Format: string);

    // Log debug-level message - lowest priority
    class procedure Debug(const Format: string);

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  // UUID support class
  TZuuid = class(TInterfacedObject, IZuuid)
  public
    FOwned: Boolean;
    FHandle: PZuuid;
    constructor Create(handle: PZuuid; owned: Boolean);
  public

    // Create a new UUID object.
    constructor New;

    // Create UUID object from supplied ZUUID_LEN-octet value.
    constructor NewFrom(Source: PByte);

    // Destroy a specified UUID object.
    destructor Destroy; override;

    // Self test of this class.
    class procedure Test(Verbose: Boolean);

    class function Wrap(handle: PZuuid; owned: Boolean): IZuuid;
    class function UnWrap(const Value: IZuuid): PZuuid;
  protected

    // Set UUID to new supplied ZUUID_LEN-octet value.
    procedure &Set(Source: PByte);

    // Set UUID to new supplied string value skipping '-' and '{' '}'
    // optional delimiters. Return 0 if OK, else returns -1.
    function SetStr(const Source: string): Integer;

    // Return UUID binary data.
    function Data: PByte;

    // Return UUID binary size
    function Size: NativeUInt;

    // Returns UUID as string
    function Str: string;

    // Return UUID in the canonical string format: 8-4-4-4-12, in lower
    // case. Caller does not modify or free returned value. See
    // http://en.wikipedia.org/wiki/Universally_unique_identifier
    function StrCanonical: string;

    // Store UUID blob in target array
    procedure Export(Target: PByte);

    // Check if UUID is same as supplied value
    function Eq(Compare: PByte): Boolean;

    // Check if UUID is different from supplied value
    function Neq(Compare: PByte): Boolean;

    // Make copy of UUID object; if uuid is null, or memory was exhausted,
    // returns null.
    function Dup: IZuuid;
  end;

  //
  TZauth = class
  public

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  //
  TZbeacon = class
  public

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  //
  TZgossip = class
  public

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  //
  TZmonitor = class
  public

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  //
  TZproxy = class
  public

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

  //
  TZrex = class
  public

    // Self test of this class.
    class procedure Test(Verbose: Boolean);
  end;

function ZFreeString(const str: PAnsiChar): string;

implementation

uses
  System.SysUtils;

function ZFreeString(const str: PAnsiChar): string;
var
  p: PAnsiChar;
begin
  Result := string(UTF8String(str));
  p := str;
  zstr_free(p);
end;

 (* TZactor *)

  constructor TZactor.New(Task: TZactorFn; Args: Pointer);
  begin
    Create(zactor_new(Task, Args), True);
  end;

  constructor TZactor.Create(handle: PZactor; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZactor.Wrap(handle: PZactor; owned: Boolean): IZactor;
  begin
    if handle <> nil then Result := TZactor.Create(handle, owned) else Result := nil;
  end;

  class function TZactor.UnWrap(const value: IZactor): PZactor;
  begin
    if value <> nil then Result := TZactor(value).FHandle else Result := nil;
  end;

  destructor TZactor.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zactor_destroy(FHandle);
  end;

  class function TZactor.&Is(This: Pointer): Boolean;
  begin
    Result := zactor_is(This);
  end;

  class function TZactor.Resolve(This: Pointer): Pointer;
  begin
    Result := zactor_resolve(This);
  end;

  class procedure TZactor.Test(Verbose: Boolean);
  begin
    zactor_test(Verbose);
  end;

  function TZactor.Send(var MsgP: IZmsg): Integer;
  begin
    Result := zactor_send(FHandle, TZmsg(MsgP).FHandle);
    if TZmsg(MsgP).FHandle = nil then
      MsgP := nil;
  end;

  function TZactor.Recv: IZmsg;
  begin
    Result := TZmsg.Wrap(zactor_recv(FHandle), true);
  end;

  function TZactor.Sock: IZsock;
  begin
    Result := TZsock.Wrap(zactor_sock(FHandle), false);
  end;

  procedure TZactor.SetDestructor(&Destructor: TZactorDestructorFn);
  begin
    zactor_set_destructor(FHandle, &Destructor);
  end;

 (* TZarmour *)

  constructor TZarmour.New;
  begin
    Create(zarmour_new, True);
  end;

  constructor TZarmour.Create(handle: PZarmour; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZarmour.Wrap(handle: PZarmour; owned: Boolean): IZarmour;
  begin
    if handle <> nil then Result := TZarmour.Create(handle, owned) else Result := nil;
  end;

  class function TZarmour.UnWrap(const value: IZarmour): PZarmour;
  begin
    if value <> nil then Result := TZarmour(value).FHandle else Result := nil;
  end;

  destructor TZarmour.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zarmour_destroy(FHandle);
  end;

  class procedure TZarmour.Test(Verbose: Boolean);
  begin
    zarmour_test(Verbose);
  end;

  function TZarmour.Encode(Data: PByte; Size: NativeUInt): string;
  begin
    Result := ZFreeString(zarmour_encode(FHandle, Data, Size));
  end;

  function TZarmour.Decode(const Data: string): IZchunk;
  var
    __Data__: UTF8String;
  begin
    __Data__ := UTF8String(Data);
    Result := TZchunk.Wrap(zarmour_decode(FHandle, PAnsiChar(__Data__)), true);
  end;

  function TZarmour.Mode: Integer;
  begin
    Result := zarmour_mode(FHandle);
  end;

  function TZarmour.ModeStr: string;
  begin
    Result := string(UTF8String(zarmour_mode_str(FHandle)));
  end;

  procedure TZarmour.SetMode(Mode: Integer);
  begin
    zarmour_set_mode(FHandle, Mode);
  end;

  function TZarmour.Pad: Boolean;
  begin
    Result := zarmour_pad(FHandle);
  end;

  procedure TZarmour.SetPad(Pad: Boolean);
  begin
    zarmour_set_pad(FHandle, Pad);
  end;

  function TZarmour.PadChar: AnsiChar;
  begin
    Result := zarmour_pad_char(FHandle);
  end;

  procedure TZarmour.SetPadChar(PadChar: AnsiChar);
  begin
    zarmour_set_pad_char(FHandle, PadChar);
  end;

  function TZarmour.LineBreaks: Boolean;
  begin
    Result := zarmour_line_breaks(FHandle);
  end;

  procedure TZarmour.SetLineBreaks(LineBreaks: Boolean);
  begin
    zarmour_set_line_breaks(FHandle, LineBreaks);
  end;

  function TZarmour.LineLength: NativeUInt;
  begin
    Result := zarmour_line_length(FHandle);
  end;

  procedure TZarmour.SetLineLength(LineLength: NativeUInt);
  begin
    zarmour_set_line_length(FHandle, LineLength);
  end;

  procedure TZarmour.Print;
  begin
    zarmour_print(FHandle);
  end;

 (* TZcert *)

  constructor TZcert.New;
  begin
    Create(zcert_new, True);
  end;

  constructor TZcert.NewFrom(PublicKey: PByte; SecretKey: PByte);
  begin
    Create(zcert_new_from(PublicKey, SecretKey), True);
  end;

  constructor TZcert.NewFromTxt(const PublicTxt: string; const SecretTxt: string);
  var
    __PublicTxt__: UTF8String;
    __SecretTxt__: UTF8String;
  begin
    __PublicTxt__ := UTF8String(PublicTxt);
    __SecretTxt__ := UTF8String(SecretTxt);
    Create(zcert_new_from_txt(PAnsiChar(__PublicTxt__), PAnsiChar(__SecretTxt__)), True);
  end;

  constructor TZcert.Load(const Filename: string);
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Create(zcert_load(PAnsiChar(__Filename__)), True);
  end;

  constructor TZcert.Create(handle: PZcert; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZcert.Wrap(handle: PZcert; owned: Boolean): IZcert;
  begin
    if handle <> nil then Result := TZcert.Create(handle, owned) else Result := nil;
  end;

  class function TZcert.UnWrap(const value: IZcert): PZcert;
  begin
    if value <> nil then Result := TZcert(value).FHandle else Result := nil;
  end;

  destructor TZcert.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zcert_destroy(FHandle);
  end;

  class procedure TZcert.Test(Verbose: Boolean);
  begin
    zcert_test(Verbose);
  end;

  function TZcert.PublicKey: PByte;
  begin
    Result := zcert_public_key(FHandle);
  end;

  function TZcert.SecretKey: PByte;
  begin
    Result := zcert_secret_key(FHandle);
  end;

  function TZcert.PublicTxt: string;
  begin
    Result := string(UTF8String(zcert_public_txt(FHandle)));
  end;

  function TZcert.SecretTxt: string;
  begin
    Result := string(UTF8String(zcert_secret_txt(FHandle)));
  end;

  procedure TZcert.SetMeta(const Name: string; const Format: string);
  var
    __Name__: UTF8String;
    __Format__: UTF8String;
  begin
    __Name__ := UTF8String(Name);
    __Format__ := UTF8String(Format);
    zcert_set_meta(FHandle, PAnsiChar(__Name__), PAnsiChar(__Format__));
  end;

  procedure TZcert.UnsetMeta(const Name: string);
  var
    __Name__: UTF8String;
  begin
    __Name__ := UTF8String(Name);
    zcert_unset_meta(FHandle, PAnsiChar(__Name__));
  end;

  function TZcert.Meta(const Name: string): string;
  var
    __Name__: UTF8String;
  begin
    __Name__ := UTF8String(Name);
    Result := string(UTF8String(zcert_meta(FHandle, PAnsiChar(__Name__))));
  end;

  function TZcert.MetaKeys: IZlist;
  begin
    Result := TZlist.Wrap(zcert_meta_keys(FHandle), false);
  end;

  function TZcert.Save(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zcert_save(FHandle, PAnsiChar(__Filename__));
  end;

  function TZcert.SavePublic(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zcert_save_public(FHandle, PAnsiChar(__Filename__));
  end;

  function TZcert.SaveSecret(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zcert_save_secret(FHandle, PAnsiChar(__Filename__));
  end;

  procedure TZcert.Apply(const Socket: IZSock);
  begin
    zcert_apply(FHandle, TZsock.UnWrap(Socket));
  end;

  function TZcert.Dup: IZcert;
  begin
    Result := TZcert.Wrap(zcert_dup(FHandle), true);
  end;

  function TZcert.Eq(const Compare: IZcert): Boolean;
  begin
    Result := zcert_eq(FHandle, TZcert.UnWrap(Compare));
  end;

  procedure TZcert.Print;
  begin
    zcert_print(FHandle);
  end;

 (* TZcertstore *)

  constructor TZcertstore.New(const Location: string);
  var
    __Location__: UTF8String;
  begin
    __Location__ := UTF8String(Location);
    Create(zcertstore_new(PAnsiChar(__Location__)), True);
  end;

  constructor TZcertstore.Create(handle: PZcertstore; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZcertstore.Wrap(handle: PZcertstore; owned: Boolean): IZcertstore;
  begin
    if handle <> nil then Result := TZcertstore.Create(handle, owned) else Result := nil;
  end;

  class function TZcertstore.UnWrap(const value: IZcertstore): PZcertstore;
  begin
    if value <> nil then Result := TZcertstore(value).FHandle else Result := nil;
  end;

  destructor TZcertstore.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zcertstore_destroy(FHandle);
  end;

  class procedure TZcertstore.Test(Verbose: Boolean);
  begin
    zcertstore_test(Verbose);
  end;

  procedure TZcertstore.SetLoader(Loader: TZcertstoreLoader; &Destructor: TZcertstoreDestructor; State: PByte);
  begin
    zcertstore_set_loader(FHandle, Loader, &Destructor, State);
  end;

  function TZcertstore.Lookup(const PublicKey: string): IZcert;
  var
    __PublicKey__: UTF8String;
  begin
    __PublicKey__ := UTF8String(PublicKey);
    Result := TZcert.Wrap(zcertstore_lookup(FHandle, PAnsiChar(__PublicKey__)), false);
  end;

  procedure TZcertstore.Insert(var CertP: IZcert);
  begin
    zcertstore_insert(FHandle, TZcert(CertP).FHandle);
    if TZcert(CertP).FHandle = nil then
      CertP := nil;
  end;

  procedure TZcertstore.Empty;
  begin
    zcertstore_empty(FHandle);
  end;

  procedure TZcertstore.Print;
  begin
    zcertstore_print(FHandle);
  end;

  function TZcertstore.Certs: IZlistx;
  begin
    Result := TZlistx.Wrap(zcertstore_certs(FHandle), true);
  end;

 (* TZchunk *)

  constructor TZchunk.New(Data: PByte; Size: NativeUInt);
  begin
    Create(zchunk_new(Data, Size), True);
  end;

  constructor TZchunk.Frommem(Data: PByte; Size: NativeUInt; &Destructor: TZchunkDestructorFn; Hint: Pointer);
  begin
    Create(zchunk_frommem(Data, Size, &Destructor, Hint), True);
  end;

  constructor TZchunk.Create(handle: PZchunk; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZchunk.Wrap(handle: PZchunk; owned: Boolean): IZchunk;
  begin
    if handle <> nil then Result := TZchunk.Create(handle, owned) else Result := nil;
  end;

  class function TZchunk.UnWrap(const value: IZchunk): PZchunk;
  begin
    if value <> nil then Result := TZchunk(value).FHandle else Result := nil;
  end;

  destructor TZchunk.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zchunk_destroy(FHandle);
  end;

  class function TZchunk.Read(Handle: Pointer; Bytes: NativeUInt): IZchunk;
  begin
    Result := TZchunk.Wrap(zchunk_read(Handle, Bytes), true);
  end;

  class function TZchunk.Slurp(const Filename: string; Maxsize: NativeUInt): IZchunk;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := TZchunk.Wrap(zchunk_slurp(PAnsiChar(__Filename__), Maxsize), true);
  end;

  class function TZchunk.Packx(var SelfP: IZchunk): IZframe;
  begin
    Result := TZframe.Wrap(zchunk_packx(TZchunk(SelfP).FHandle), true);
    if TZchunk(SelfP).FHandle = nil then
      SelfP := nil;
  end;

  class function TZchunk.Unpack(const Frame: IZframe): IZchunk;
  begin
    Result := TZchunk.Wrap(zchunk_unpack(TZframe.UnWrap(Frame)), true);
  end;

  class function TZchunk.&Is(This: Pointer): Boolean;
  begin
    Result := zchunk_is(This);
  end;

  class procedure TZchunk.Test(Verbose: Boolean);
  begin
    zchunk_test(Verbose);
  end;

  procedure TZchunk.Resize(Size: NativeUInt);
  begin
    zchunk_resize(FHandle, Size);
  end;

  function TZchunk.Size: NativeUInt;
  begin
    Result := zchunk_size(FHandle);
  end;

  function TZchunk.MaxSize: NativeUInt;
  begin
    Result := zchunk_max_size(FHandle);
  end;

  function TZchunk.Data: PByte;
  begin
    Result := zchunk_data(FHandle);
  end;

  function TZchunk.&Set(Data: PByte; Size: NativeUInt): NativeUInt;
  begin
    Result := zchunk_set(FHandle, Data, Size);
  end;

  function TZchunk.Fill(Filler: Byte; Size: NativeUInt): NativeUInt;
  begin
    Result := zchunk_fill(FHandle, Filler, Size);
  end;

  function TZchunk.Append(Data: PByte; Size: NativeUInt): NativeUInt;
  begin
    Result := zchunk_append(FHandle, Data, Size);
  end;

  function TZchunk.Extend(Data: PByte; Size: NativeUInt): NativeUInt;
  begin
    Result := zchunk_extend(FHandle, Data, Size);
  end;

  function TZchunk.Consume(const Source: IZchunk): NativeUInt;
  begin
    Result := zchunk_consume(FHandle, TZchunk.UnWrap(Source));
  end;

  function TZchunk.Exhausted: Boolean;
  begin
    Result := zchunk_exhausted(FHandle);
  end;

  function TZchunk.Write(Handle: Pointer): Integer;
  begin
    Result := zchunk_write(FHandle, Handle);
  end;

  function TZchunk.Dup: IZchunk;
  begin
    Result := TZchunk.Wrap(zchunk_dup(FHandle), true);
  end;

  function TZchunk.Strhex: string;
  begin
    Result := ZFreeString(zchunk_strhex(FHandle));
  end;

  function TZchunk.Strdup: string;
  begin
    Result := ZFreeString(zchunk_strdup(FHandle));
  end;

  function TZchunk.Streq(const &String: string): Boolean;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zchunk_streq(FHandle, PAnsiChar(__String__));
  end;

  function TZchunk.Pack: IZframe;
  begin
    Result := TZframe.Wrap(zchunk_pack(FHandle), true);
  end;

  function TZchunk.Digest: string;
  begin
    Result := string(UTF8String(zchunk_digest(FHandle)));
  end;

  procedure TZchunk.Fprint(&File: Pointer);
  begin
    zchunk_fprint(FHandle, &File);
  end;

  procedure TZchunk.Print;
  begin
    zchunk_print(FHandle);
  end;

 (* TZclock *)

  class procedure TZclock.Sleep(Msecs: Integer);
  begin
    zclock_sleep(Msecs);
  end;

  class function TZclock.Time: Int64;
  begin
    Result := zclock_time;
  end;

  class function TZclock.Mono: Int64;
  begin
    Result := zclock_mono;
  end;

  class function TZclock.Usecs: Int64;
  begin
    Result := zclock_usecs;
  end;

  class function TZclock.Timestr: string;
  begin
    Result := ZFreeString(zclock_timestr);
  end;

  class procedure TZclock.Test(Verbose: Boolean);
  begin
    zclock_test(Verbose);
  end;

 (* TZconfig *)

  constructor TZconfig.New(const Name: string; const Parent: IZconfig);
  var
    __Name__: UTF8String;
  begin
    __Name__ := UTF8String(Name);
    Create(zconfig_new(PAnsiChar(__Name__), TZconfig.UnWrap(Parent)), True);
  end;

  constructor TZconfig.Load(const Filename: string);
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Create(zconfig_load(PAnsiChar(__Filename__)), True);
  end;

  constructor TZconfig.Loadf(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Create(zconfig_loadf(PAnsiChar(__Format__)), True);
  end;

  constructor TZconfig.Create(handle: PZconfig; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZconfig.Wrap(handle: PZconfig; owned: Boolean): IZconfig;
  begin
    if handle <> nil then Result := TZconfig.Create(handle, owned) else Result := nil;
  end;

  class function TZconfig.UnWrap(const value: IZconfig): PZconfig;
  begin
    if value <> nil then Result := TZconfig(value).FHandle else Result := nil;
  end;

  destructor TZconfig.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zconfig_destroy(FHandle);
  end;

  class function TZconfig.Reload(var SelfP: IZconfig): Integer;
  begin
    Result := zconfig_reload(TZconfig(SelfP).FHandle);
    if TZconfig(SelfP).FHandle = nil then
      SelfP := nil;
  end;

  class function TZconfig.ChunkLoad(const Chunk: IZchunk): IZconfig;
  begin
    Result := TZconfig.Wrap(zconfig_chunk_load(TZchunk.UnWrap(Chunk)), false);
  end;

  class function TZconfig.StrLoad(const &String: string): IZconfig;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := TZconfig.Wrap(zconfig_str_load(PAnsiChar(__String__)), true);
  end;

  class procedure TZconfig.Remove(var SelfP: IZconfig);
  begin
    zconfig_remove(TZconfig(SelfP).FHandle);
    if TZconfig(SelfP).FHandle = nil then
      SelfP := nil;
  end;

  class procedure TZconfig.Test(Verbose: Boolean);
  begin
    zconfig_test(Verbose);
  end;

  function TZconfig.Dup: IZconfig;
  begin
    Result := TZconfig.Wrap(zconfig_dup(FHandle), true);
  end;

  function TZconfig.Name: string;
  begin
    Result := string(UTF8String(zconfig_name(FHandle)));
  end;

  function TZconfig.Value: string;
  begin
    Result := string(UTF8String(zconfig_value(FHandle)));
  end;

  procedure TZconfig.Put(const Path: string; const Value: string);
  var
    __Path__: UTF8String;
    __Value__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    __Value__ := UTF8String(Value);
    zconfig_put(FHandle, PAnsiChar(__Path__), PAnsiChar(__Value__));
  end;

  procedure TZconfig.Putf(const Path: string; const Format: string);
  var
    __Path__: UTF8String;
    __Format__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    __Format__ := UTF8String(Format);
    zconfig_putf(FHandle, PAnsiChar(__Path__), PAnsiChar(__Format__));
  end;

  function TZconfig.Get(const Path: string; const DefaultValue: string): string;
  var
    __Path__: UTF8String;
    __DefaultValue__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    __DefaultValue__ := UTF8String(DefaultValue);
    Result := string(UTF8String(zconfig_get(FHandle, PAnsiChar(__Path__), PAnsiChar(__DefaultValue__))));
  end;

  procedure TZconfig.SetName(const Name: string);
  var
    __Name__: UTF8String;
  begin
    __Name__ := UTF8String(Name);
    zconfig_set_name(FHandle, PAnsiChar(__Name__));
  end;

  procedure TZconfig.SetValue(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zconfig_set_value(FHandle, PAnsiChar(__Format__));
  end;

  function TZconfig.Child: IZconfig;
  begin
    Result := TZconfig.Wrap(zconfig_child(FHandle), false);
  end;

  function TZconfig.Next: IZconfig;
  begin
    Result := TZconfig.Wrap(zconfig_next(FHandle), false);
  end;

  function TZconfig.Locate(const Path: string): IZconfig;
  var
    __Path__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    Result := TZconfig.Wrap(zconfig_locate(FHandle, PAnsiChar(__Path__)), false);
  end;

  function TZconfig.AtDepth(Level: Integer): IZconfig;
  begin
    Result := TZconfig.Wrap(zconfig_at_depth(FHandle, Level), false);
  end;

  function TZconfig.Execute(Handler: TZconfigFct; Arg: Pointer): Integer;
  begin
    Result := zconfig_execute(FHandle, Handler, Arg);
  end;

  procedure TZconfig.SetComment(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zconfig_set_comment(FHandle, PAnsiChar(__Format__));
  end;

  function TZconfig.Comments: IZlist;
  begin
    Result := TZlist.Wrap(zconfig_comments(FHandle), false);
  end;

  function TZconfig.Save(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zconfig_save(FHandle, PAnsiChar(__Filename__));
  end;

  function TZconfig.Savef(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zconfig_savef(FHandle, PAnsiChar(__Format__));
  end;

  function TZconfig.Filename: string;
  begin
    Result := string(UTF8String(zconfig_filename(FHandle)));
  end;

  function TZconfig.ChunkSave: IZchunk;
  begin
    Result := TZchunk.Wrap(zconfig_chunk_save(FHandle), false);
  end;

  function TZconfig.StrSave: string;
  begin
    Result := ZFreeString(zconfig_str_save(FHandle));
  end;

  function TZconfig.HasChanged: Boolean;
  begin
    Result := zconfig_has_changed(FHandle);
  end;

  procedure TZconfig.RemoveSubtree;
  begin
    zconfig_remove_subtree(FHandle);
  end;

  procedure TZconfig.Fprint(&File: Pointer);
  begin
    zconfig_fprint(FHandle, &File);
  end;

  procedure TZconfig.Print;
  begin
    zconfig_print(FHandle);
  end;

 (* TZdigest *)

  constructor TZdigest.New;
  begin
    Create(zdigest_new, True);
  end;

  constructor TZdigest.Create(handle: PZdigest; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZdigest.Wrap(handle: PZdigest; owned: Boolean): IZdigest;
  begin
    if handle <> nil then Result := TZdigest.Create(handle, owned) else Result := nil;
  end;

  class function TZdigest.UnWrap(const value: IZdigest): PZdigest;
  begin
    if value <> nil then Result := TZdigest(value).FHandle else Result := nil;
  end;

  destructor TZdigest.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zdigest_destroy(FHandle);
  end;

  class procedure TZdigest.Test(Verbose: Boolean);
  begin
    zdigest_test(Verbose);
  end;

  procedure TZdigest.Update(Buffer: PByte; Length: NativeUInt);
  begin
    zdigest_update(FHandle, Buffer, Length);
  end;

  function TZdigest.Data: PByte;
  begin
    Result := zdigest_data(FHandle);
  end;

  function TZdigest.Size: NativeUInt;
  begin
    Result := zdigest_size(FHandle);
  end;

  function TZdigest.&String: string;
  begin
    Result := string(UTF8String(zdigest_string(FHandle)));
  end;

 (* TZdir *)

  constructor TZdir.New(const Path: string; const Parent: string);
  var
    __Path__: UTF8String;
    __Parent__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    __Parent__ := UTF8String(Parent);
    Create(zdir_new(PAnsiChar(__Path__), PAnsiChar(__Parent__)), True);
  end;

  constructor TZdir.Create(handle: PZdir; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZdir.Wrap(handle: PZdir; owned: Boolean): IZdir;
  begin
    if handle <> nil then Result := TZdir.Create(handle, owned) else Result := nil;
  end;

  class function TZdir.UnWrap(const value: IZdir): PZdir;
  begin
    if value <> nil then Result := TZdir(value).FHandle else Result := nil;
  end;

  destructor TZdir.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zdir_destroy(FHandle);
  end;

  class function TZdir.Diff(const Older: IZdir; const Newer: IZdir; const Alias: string): IZlist;
  var
    __Alias__: UTF8String;
  begin
    __Alias__ := UTF8String(Alias);
    Result := TZlist.Wrap(zdir_diff(TZdir.UnWrap(Older), TZdir.UnWrap(Newer), PAnsiChar(__Alias__)), true);
  end;

  class procedure TZdir.Watch(const Pipe: IZsock; Unused: Pointer);
  begin
    zdir_watch(TZsock.UnWrap(Pipe), Unused);
  end;

  class procedure TZdir.Test(Verbose: Boolean);
  begin
    zdir_test(Verbose);
  end;

  function TZdir.Path: string;
  begin
    Result := string(UTF8String(zdir_path(FHandle)));
  end;

  function TZdir.Modified: Int64;
  begin
    Result := zdir_modified(FHandle);
  end;

  function TZdir.Cursize: Longint;
  begin
    Result := zdir_cursize(FHandle);
  end;

  function TZdir.Count: NativeUInt;
  begin
    Result := zdir_count(FHandle);
  end;

  function TZdir.List: IZlist;
  begin
    Result := TZlist.Wrap(zdir_list(FHandle), true);
  end;

  procedure TZdir.Remove(Force: Boolean);
  begin
    zdir_remove(FHandle, Force);
  end;

  function TZdir.Resync(const Alias: string): IZlist;
  var
    __Alias__: UTF8String;
  begin
    __Alias__ := UTF8String(Alias);
    Result := TZlist.Wrap(zdir_resync(FHandle, PAnsiChar(__Alias__)), true);
  end;

  function TZdir.Cache: IZhash;
  begin
    Result := TZhash.Wrap(zdir_cache(FHandle), true);
  end;

  procedure TZdir.Fprint(&File: Pointer; Indent: Integer);
  begin
    zdir_fprint(FHandle, &File, Indent);
  end;

  procedure TZdir.Print(Indent: Integer);
  begin
    zdir_print(FHandle, Indent);
  end;

 (* TZdirPatch *)

  constructor TZdirPatch.New(const Path: string; const &File: IZfile; Op: Integer; const Alias: string);
  var
    __Path__: UTF8String;
    __Alias__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    __Alias__ := UTF8String(Alias);
    Create(zdir_patch_new(PAnsiChar(__Path__), TZfile.UnWrap(&File), Op, PAnsiChar(__Alias__)), True);
  end;

  constructor TZdirPatch.Create(handle: PZdirPatch; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZdirPatch.Wrap(handle: PZdirPatch; owned: Boolean): IZdirPatch;
  begin
    if handle <> nil then Result := TZdirPatch.Create(handle, owned) else Result := nil;
  end;

  class function TZdirPatch.UnWrap(const value: IZdirPatch): PZdirPatch;
  begin
    if value <> nil then Result := TZdirPatch(value).FHandle else Result := nil;
  end;

  destructor TZdirPatch.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zdir_patch_destroy(FHandle);
  end;

  class procedure TZdirPatch.Test(Verbose: Boolean);
  begin
    zdir_patch_test(Verbose);
  end;

  function TZdirPatch.Dup: IZdirPatch;
  begin
    Result := TZdirPatch.Wrap(zdir_patch_dup(FHandle), true);
  end;

  function TZdirPatch.Path: string;
  begin
    Result := string(UTF8String(zdir_patch_path(FHandle)));
  end;

  function TZdirPatch.&File: IZfile;
  begin
    Result := TZfile.Wrap(zdir_patch_file(FHandle), false);
  end;

  function TZdirPatch.Op: Integer;
  begin
    Result := zdir_patch_op(FHandle);
  end;

  function TZdirPatch.Vpath: string;
  begin
    Result := string(UTF8String(zdir_patch_vpath(FHandle)));
  end;

  procedure TZdirPatch.DigestSet;
  begin
    zdir_patch_digest_set(FHandle);
  end;

  function TZdirPatch.Digest: string;
  begin
    Result := string(UTF8String(zdir_patch_digest(FHandle)));
  end;

 (* TZfile *)

  constructor TZfile.New(const Path: string; const Name: string);
  var
    __Path__: UTF8String;
    __Name__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    __Name__ := UTF8String(Name);
    Create(zfile_new(PAnsiChar(__Path__), PAnsiChar(__Name__)), True);
  end;

  constructor TZfile.Tmp;
  begin
    Create(zfile_tmp, True);
  end;

  constructor TZfile.Create(handle: PZfile; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZfile.Wrap(handle: PZfile; owned: Boolean): IZfile;
  begin
    if handle <> nil then Result := TZfile.Create(handle, owned) else Result := nil;
  end;

  class function TZfile.UnWrap(const value: IZfile): PZfile;
  begin
    if value <> nil then Result := TZfile(value).FHandle else Result := nil;
  end;

  destructor TZfile.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zfile_destroy(FHandle);
  end;

  class procedure TZfile.Test(Verbose: Boolean);
  begin
    zfile_test(Verbose);
  end;

  function TZfile.Dup: IZfile;
  begin
    Result := TZfile.Wrap(zfile_dup(FHandle), true);
  end;

  function TZfile.Filename(const Path: string): string;
  var
    __Path__: UTF8String;
  begin
    __Path__ := UTF8String(Path);
    Result := string(UTF8String(zfile_filename(FHandle, PAnsiChar(__Path__))));
  end;

  procedure TZfile.Restat;
  begin
    zfile_restat(FHandle);
  end;

  function TZfile.Modified: Int64;
  begin
    Result := zfile_modified(FHandle);
  end;

  function TZfile.Cursize: Longint;
  begin
    Result := zfile_cursize(FHandle);
  end;

  function TZfile.IsDirectory: Boolean;
  begin
    Result := zfile_is_directory(FHandle);
  end;

  function TZfile.IsRegular: Boolean;
  begin
    Result := zfile_is_regular(FHandle);
  end;

  function TZfile.IsReadable: Boolean;
  begin
    Result := zfile_is_readable(FHandle);
  end;

  function TZfile.IsWriteable: Boolean;
  begin
    Result := zfile_is_writeable(FHandle);
  end;

  function TZfile.IsStable: Boolean;
  begin
    Result := zfile_is_stable(FHandle);
  end;

  function TZfile.HasChanged: Boolean;
  begin
    Result := zfile_has_changed(FHandle);
  end;

  procedure TZfile.Remove;
  begin
    zfile_remove(FHandle);
  end;

  function TZfile.Input: Integer;
  begin
    Result := zfile_input(FHandle);
  end;

  function TZfile.Output: Integer;
  begin
    Result := zfile_output(FHandle);
  end;

  function TZfile.Read(Bytes: NativeUInt; Offset: Longint): IZchunk;
  begin
    Result := TZchunk.Wrap(zfile_read(FHandle, Bytes, Offset), true);
  end;

  function TZfile.Eof: Boolean;
  begin
    Result := zfile_eof(FHandle);
  end;

  function TZfile.Write(const Chunk: IZchunk; Offset: Longint): Integer;
  begin
    Result := zfile_write(FHandle, TZchunk.UnWrap(Chunk), Offset);
  end;

  function TZfile.Readln: string;
  begin
    Result := string(UTF8String(zfile_readln(FHandle)));
  end;

  procedure TZfile.Close;
  begin
    zfile_close(FHandle);
  end;

  function TZfile.Handle: Pointer;
  begin
    Result := zfile_handle(FHandle);
  end;

  function TZfile.Digest: string;
  begin
    Result := string(UTF8String(zfile_digest(FHandle)));
  end;

 (* TZframe *)

  constructor TZframe.New(Data: PByte; Size: NativeUInt);
  begin
    Create(zframe_new(Data, Size), True);
  end;

  constructor TZframe.NewEmpty;
  begin
    Create(zframe_new_empty, True);
  end;

  constructor TZframe.From(const &String: string);
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Create(zframe_from(PAnsiChar(__String__)), True);
  end;

  constructor TZframe.Frommem(Data: PByte; Size: NativeUInt; &Destructor: TZframeDestructorFn; Hint: Pointer);
  begin
    Create(zframe_frommem(Data, Size, &Destructor, Hint), True);
  end;

  constructor TZframe.Recv(const Source: IZSock);
  begin
    Create(zframe_recv(TZsock.UnWrap(Source)), True);
  end;

  constructor TZframe.Create(handle: PZframe; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZframe.Wrap(handle: PZframe; owned: Boolean): IZframe;
  begin
    if handle <> nil then Result := TZframe.Create(handle, owned) else Result := nil;
  end;

  class function TZframe.UnWrap(const value: IZframe): PZframe;
  begin
    if value <> nil then Result := TZframe(value).FHandle else Result := nil;
  end;

  destructor TZframe.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zframe_destroy(FHandle);
  end;

  class function TZframe.Send(var SelfP: IZframe; const Dest: IZSock; Flags: Integer): Integer;
  begin
    Result := zframe_send(TZframe(SelfP).FHandle, TZsock.UnWrap(Dest), Flags);
    if TZframe(SelfP).FHandle = nil then
      SelfP := nil;
  end;

  class function TZframe.&Is(This: Pointer): Boolean;
  begin
    Result := zframe_is(This);
  end;

  class procedure TZframe.Test(Verbose: Boolean);
  begin
    zframe_test(Verbose);
  end;

  function TZframe.Size: NativeUInt;
  begin
    Result := zframe_size(FHandle);
  end;

  function TZframe.Data: PByte;
  begin
    Result := zframe_data(FHandle);
  end;

  function TZframe.Meta(const &Property: string): string;
  var
    __Property__: UTF8String;
  begin
    __Property__ := UTF8String(&Property);
    Result := string(UTF8String(zframe_meta(FHandle, PAnsiChar(__Property__))));
  end;

  function TZframe.Dup: IZframe;
  begin
    Result := TZframe.Wrap(zframe_dup(FHandle), true);
  end;

  function TZframe.Strhex: string;
  begin
    Result := ZFreeString(zframe_strhex(FHandle));
  end;

  function TZframe.Strdup: string;
  begin
    Result := ZFreeString(zframe_strdup(FHandle));
  end;

  function TZframe.Streq(const &String: string): Boolean;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zframe_streq(FHandle, PAnsiChar(__String__));
  end;

  function TZframe.More: Integer;
  begin
    Result := zframe_more(FHandle);
  end;

  procedure TZframe.SetMore(More: Integer);
  begin
    zframe_set_more(FHandle, More);
  end;

  function TZframe.RoutingId: Cardinal;
  begin
    Result := zframe_routing_id(FHandle);
  end;

  procedure TZframe.SetRoutingId(RoutingId: Cardinal);
  begin
    zframe_set_routing_id(FHandle, RoutingId);
  end;

  function TZframe.Group: string;
  begin
    Result := string(UTF8String(zframe_group(FHandle)));
  end;

  function TZframe.SetGroup(const Group: string): Integer;
  var
    __Group__: UTF8String;
  begin
    __Group__ := UTF8String(Group);
    Result := zframe_set_group(FHandle, PAnsiChar(__Group__));
  end;

  function TZframe.Eq(const Other: IZframe): Boolean;
  begin
    Result := zframe_eq(FHandle, TZframe.UnWrap(Other));
  end;

  procedure TZframe.Reset(Data: PByte; Size: NativeUInt);
  begin
    zframe_reset(FHandle, Data, Size);
  end;

  procedure TZframe.Print(const Prefix: string);
  var
    __Prefix__: UTF8String;
  begin
    __Prefix__ := UTF8String(Prefix);
    zframe_print(FHandle, PAnsiChar(__Prefix__));
  end;

 (* TZhash *)

  constructor TZhash.New;
  begin
    Create(zhash_new, True);
  end;

  constructor TZhash.Unpack(const Frame: IZframe);
  begin
    Create(zhash_unpack(TZframe.UnWrap(Frame)), True);
  end;

  constructor TZhash.Create(handle: PZhash; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZhash.Wrap(handle: PZhash; owned: Boolean): IZhash;
  begin
    if handle <> nil then Result := TZhash.Create(handle, owned) else Result := nil;
  end;

  class function TZhash.UnWrap(const value: IZhash): PZhash;
  begin
    if value <> nil then Result := TZhash(value).FHandle else Result := nil;
  end;

  destructor TZhash.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zhash_destroy(FHandle);
  end;

  class procedure TZhash.Test(Verbose: Boolean);
  begin
    zhash_test(Verbose);
  end;

  function TZhash.Insert(const Key: string; Item: Pointer): Integer;
  var
    __Key__: UTF8String;
  begin
    __Key__ := UTF8String(Key);
    Result := zhash_insert(FHandle, PAnsiChar(__Key__), Item);
  end;

  procedure TZhash.Update(const Key: string; Item: Pointer);
  var
    __Key__: UTF8String;
  begin
    __Key__ := UTF8String(Key);
    zhash_update(FHandle, PAnsiChar(__Key__), Item);
  end;

  procedure TZhash.Delete(const Key: string);
  var
    __Key__: UTF8String;
  begin
    __Key__ := UTF8String(Key);
    zhash_delete(FHandle, PAnsiChar(__Key__));
  end;

  function TZhash.Lookup(const Key: string): Pointer;
  var
    __Key__: UTF8String;
  begin
    __Key__ := UTF8String(Key);
    Result := zhash_lookup(FHandle, PAnsiChar(__Key__));
  end;

  function TZhash.Rename(const OldKey: string; const NewKey: string): Integer;
  var
    __OldKey__: UTF8String;
    __NewKey__: UTF8String;
  begin
    __OldKey__ := UTF8String(OldKey);
    __NewKey__ := UTF8String(NewKey);
    Result := zhash_rename(FHandle, PAnsiChar(__OldKey__), PAnsiChar(__NewKey__));
  end;

  function TZhash.Freefn(const Key: string; FreeFn: TZhashFreeFn): Pointer;
  var
    __Key__: UTF8String;
  begin
    __Key__ := UTF8String(Key);
    Result := zhash_freefn(FHandle, PAnsiChar(__Key__), FreeFn);
  end;

  function TZhash.Size: NativeUInt;
  begin
    Result := zhash_size(FHandle);
  end;

  function TZhash.Dup: IZhash;
  begin
    Result := TZhash.Wrap(zhash_dup(FHandle), true);
  end;

  function TZhash.Keys: IZlist;
  begin
    Result := TZlist.Wrap(zhash_keys(FHandle), true);
  end;

  function TZhash.First: Pointer;
  begin
    Result := zhash_first(FHandle);
  end;

  function TZhash.Next: Pointer;
  begin
    Result := zhash_next(FHandle);
  end;

  function TZhash.Cursor: string;
  begin
    Result := string(UTF8String(zhash_cursor(FHandle)));
  end;

  procedure TZhash.Comment(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zhash_comment(FHandle, PAnsiChar(__Format__));
  end;

  function TZhash.Pack: IZframe;
  begin
    Result := TZframe.Wrap(zhash_pack(FHandle), true);
  end;

  function TZhash.Save(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zhash_save(FHandle, PAnsiChar(__Filename__));
  end;

  function TZhash.Load(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zhash_load(FHandle, PAnsiChar(__Filename__));
  end;

  function TZhash.Refresh: Integer;
  begin
    Result := zhash_refresh(FHandle);
  end;

  procedure TZhash.Autofree;
  begin
    zhash_autofree(FHandle);
  end;

 (* TZhashx *)

  constructor TZhashx.New;
  begin
    Create(zhashx_new, True);
  end;

  constructor TZhashx.Unpack(const Frame: IZframe);
  begin
    Create(zhashx_unpack(TZframe.UnWrap(Frame)), True);
  end;

  constructor TZhashx.UnpackOwn(const Frame: IZframe; Deserializer: TZhashxDeserializerFn);
  begin
    Create(zhashx_unpack_own(TZframe.UnWrap(Frame), Deserializer), True);
  end;

  constructor TZhashx.Create(handle: PZhashx; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZhashx.Wrap(handle: PZhashx; owned: Boolean): IZhashx;
  begin
    if handle <> nil then Result := TZhashx.Create(handle, owned) else Result := nil;
  end;

  class function TZhashx.UnWrap(const value: IZhashx): PZhashx;
  begin
    if value <> nil then Result := TZhashx(value).FHandle else Result := nil;
  end;

  destructor TZhashx.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zhashx_destroy(FHandle);
  end;

  class procedure TZhashx.Test(Verbose: Boolean);
  begin
    zhashx_test(Verbose);
  end;

  function TZhashx.Insert(Key: Pointer; Item: Pointer): Integer;
  begin
    Result := zhashx_insert(FHandle, Key, Item);
  end;

  procedure TZhashx.Update(Key: Pointer; Item: Pointer);
  begin
    zhashx_update(FHandle, Key, Item);
  end;

  procedure TZhashx.Delete(Key: Pointer);
  begin
    zhashx_delete(FHandle, Key);
  end;

  procedure TZhashx.Purge;
  begin
    zhashx_purge(FHandle);
  end;

  function TZhashx.Lookup(Key: Pointer): Pointer;
  begin
    Result := zhashx_lookup(FHandle, Key);
  end;

  function TZhashx.Rename(OldKey: Pointer; NewKey: Pointer): Integer;
  begin
    Result := zhashx_rename(FHandle, OldKey, NewKey);
  end;

  function TZhashx.Freefn(Key: Pointer; FreeFn: TZhashxFreeFn): Pointer;
  begin
    Result := zhashx_freefn(FHandle, Key, FreeFn);
  end;

  function TZhashx.Size: NativeUInt;
  begin
    Result := zhashx_size(FHandle);
  end;

  function TZhashx.Keys: IZlistx;
  begin
    Result := TZlistx.Wrap(zhashx_keys(FHandle), true);
  end;

  function TZhashx.Values: IZlistx;
  begin
    Result := TZlistx.Wrap(zhashx_values(FHandle), true);
  end;

  function TZhashx.First: Pointer;
  begin
    Result := zhashx_first(FHandle);
  end;

  function TZhashx.Next: Pointer;
  begin
    Result := zhashx_next(FHandle);
  end;

  function TZhashx.Cursor: Pointer;
  begin
    Result := zhashx_cursor(FHandle);
  end;

  procedure TZhashx.Comment(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zhashx_comment(FHandle, PAnsiChar(__Format__));
  end;

  function TZhashx.Save(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zhashx_save(FHandle, PAnsiChar(__Filename__));
  end;

  function TZhashx.Load(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zhashx_load(FHandle, PAnsiChar(__Filename__));
  end;

  function TZhashx.Refresh: Integer;
  begin
    Result := zhashx_refresh(FHandle);
  end;

  function TZhashx.Pack: IZframe;
  begin
    Result := TZframe.Wrap(zhashx_pack(FHandle), true);
  end;

  function TZhashx.PackOwn(Serializer: TZhashxSerializerFn): IZframe;
  begin
    Result := TZframe.Wrap(zhashx_pack_own(FHandle, Serializer), true);
  end;

  function TZhashx.Dup: IZhashx;
  begin
    Result := TZhashx.Wrap(zhashx_dup(FHandle), true);
  end;

  procedure TZhashx.SetDestructor(&Destructor: TZhashxDestructorFn);
  begin
    zhashx_set_destructor(FHandle, &Destructor);
  end;

  procedure TZhashx.SetDuplicator(Duplicator: TZhashxDuplicatorFn);
  begin
    zhashx_set_duplicator(FHandle, Duplicator);
  end;

  procedure TZhashx.SetKeyDestructor(&Destructor: TZhashxDestructorFn);
  begin
    zhashx_set_key_destructor(FHandle, &Destructor);
  end;

  procedure TZhashx.SetKeyDuplicator(Duplicator: TZhashxDuplicatorFn);
  begin
    zhashx_set_key_duplicator(FHandle, Duplicator);
  end;

  procedure TZhashx.SetKeyComparator(Comparator: TZhashxComparatorFn);
  begin
    zhashx_set_key_comparator(FHandle, Comparator);
  end;

  procedure TZhashx.SetKeyHasher(Hasher: TZhashxHashFn);
  begin
    zhashx_set_key_hasher(FHandle, Hasher);
  end;

  function TZhashx.DupV2: IZhashx;
  begin
    Result := TZhashx.Wrap(zhashx_dup_v2(FHandle), false);
  end;

 (* TZiflist *)

  constructor TZiflist.New;
  begin
    Create(ziflist_new, True);
  end;

  constructor TZiflist.Create(handle: PZiflist; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZiflist.Wrap(handle: PZiflist; owned: Boolean): IZiflist;
  begin
    if handle <> nil then Result := TZiflist.Create(handle, owned) else Result := nil;
  end;

  class function TZiflist.UnWrap(const value: IZiflist): PZiflist;
  begin
    if value <> nil then Result := TZiflist(value).FHandle else Result := nil;
  end;

  destructor TZiflist.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      ziflist_destroy(FHandle);
  end;

  class function TZiflist.NewIpv6: IZiflist;
  begin
    Result := TZiflist.Wrap(ziflist_new_ipv6, true);
  end;

  class procedure TZiflist.Test(Verbose: Boolean);
  begin
    ziflist_test(Verbose);
  end;

  procedure TZiflist.Reload;
  begin
    ziflist_reload(FHandle);
  end;

  function TZiflist.Size: NativeUInt;
  begin
    Result := ziflist_size(FHandle);
  end;

  function TZiflist.First: string;
  begin
    Result := string(UTF8String(ziflist_first(FHandle)));
  end;

  function TZiflist.Next: string;
  begin
    Result := string(UTF8String(ziflist_next(FHandle)));
  end;

  function TZiflist.Address: string;
  begin
    Result := string(UTF8String(ziflist_address(FHandle)));
  end;

  function TZiflist.Broadcast: string;
  begin
    Result := string(UTF8String(ziflist_broadcast(FHandle)));
  end;

  function TZiflist.Netmask: string;
  begin
    Result := string(UTF8String(ziflist_netmask(FHandle)));
  end;

  procedure TZiflist.Print;
  begin
    ziflist_print(FHandle);
  end;

  procedure TZiflist.ReloadIpv6;
  begin
    ziflist_reload_ipv6(FHandle);
  end;

  function TZiflist.IsIpv6: Boolean;
  begin
    Result := ziflist_is_ipv6(FHandle);
  end;

 (* TZlist *)

  constructor TZlist.New;
  begin
    Create(zlist_new, True);
  end;

  constructor TZlist.Create(handle: PZlist; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZlist.Wrap(handle: PZlist; owned: Boolean): IZlist;
  begin
    if handle <> nil then Result := TZlist.Create(handle, owned) else Result := nil;
  end;

  class function TZlist.UnWrap(const value: IZlist): PZlist;
  begin
    if value <> nil then Result := TZlist(value).FHandle else Result := nil;
  end;

  destructor TZlist.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zlist_destroy(FHandle);
  end;

  class procedure TZlist.Test(Verbose: Boolean);
  begin
    zlist_test(Verbose);
  end;

  function TZlist.First: Pointer;
  begin
    Result := zlist_first(FHandle);
  end;

  function TZlist.Next: Pointer;
  begin
    Result := zlist_next(FHandle);
  end;

  function TZlist.Last: Pointer;
  begin
    Result := zlist_last(FHandle);
  end;

  function TZlist.Head: Pointer;
  begin
    Result := zlist_head(FHandle);
  end;

  function TZlist.Tail: Pointer;
  begin
    Result := zlist_tail(FHandle);
  end;

  function TZlist.Item: Pointer;
  begin
    Result := zlist_item(FHandle);
  end;

  function TZlist.Append(Item: Pointer): Integer;
  begin
    Result := zlist_append(FHandle, Item);
  end;

  function TZlist.Push(Item: Pointer): Integer;
  begin
    Result := zlist_push(FHandle, Item);
  end;

  function TZlist.Pop: Pointer;
  begin
    Result := zlist_pop(FHandle);
  end;

  function TZlist.Exists(Item: Pointer): Boolean;
  begin
    Result := zlist_exists(FHandle, Item);
  end;

  procedure TZlist.Remove(Item: Pointer);
  begin
    zlist_remove(FHandle, Item);
  end;

  function TZlist.Dup: IZlist;
  begin
    Result := TZlist.Wrap(zlist_dup(FHandle), true);
  end;

  procedure TZlist.Purge;
  begin
    zlist_purge(FHandle);
  end;

  function TZlist.Size: NativeUInt;
  begin
    Result := zlist_size(FHandle);
  end;

  procedure TZlist.Sort(Compare: TZlistCompareFn);
  begin
    zlist_sort(FHandle, Compare);
  end;

  procedure TZlist.Autofree;
  begin
    zlist_autofree(FHandle);
  end;

  procedure TZlist.Comparefn(Fn: TZlistCompareFn);
  begin
    zlist_comparefn(FHandle, Fn);
  end;

  function TZlist.Freefn(Item: Pointer; Fn: TZlistFreeFn; AtTail: Boolean): Pointer;
  begin
    Result := zlist_freefn(FHandle, Item, Fn, AtTail);
  end;

 (* TZlistx *)

  constructor TZlistx.New;
  begin
    Create(zlistx_new, True);
  end;

  constructor TZlistx.Unpack(const Frame: IZframe);
  begin
    Create(zlistx_unpack(TZframe.UnWrap(Frame)), True);
  end;

  constructor TZlistx.Create(handle: PZlistx; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZlistx.Wrap(handle: PZlistx; owned: Boolean): IZlistx;
  begin
    if handle <> nil then Result := TZlistx.Create(handle, owned) else Result := nil;
  end;

  class function TZlistx.UnWrap(const value: IZlistx): PZlistx;
  begin
    if value <> nil then Result := TZlistx(value).FHandle else Result := nil;
  end;

  destructor TZlistx.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zlistx_destroy(FHandle);
  end;

  class function TZlistx.HandleItem(Handle: Pointer): Pointer;
  begin
    Result := zlistx_handle_item(Handle);
  end;

  class procedure TZlistx.Test(Verbose: Boolean);
  begin
    zlistx_test(Verbose);
  end;

  function TZlistx.AddStart(Item: Pointer): Pointer;
  begin
    Result := zlistx_add_start(FHandle, Item);
  end;

  function TZlistx.AddEnd(Item: Pointer): Pointer;
  begin
    Result := zlistx_add_end(FHandle, Item);
  end;

  function TZlistx.Size: NativeUInt;
  begin
    Result := zlistx_size(FHandle);
  end;

  function TZlistx.Head: Pointer;
  begin
    Result := zlistx_head(FHandle);
  end;

  function TZlistx.Tail: Pointer;
  begin
    Result := zlistx_tail(FHandle);
  end;

  function TZlistx.First: Pointer;
  begin
    Result := zlistx_first(FHandle);
  end;

  function TZlistx.Next: Pointer;
  begin
    Result := zlistx_next(FHandle);
  end;

  function TZlistx.Prev: Pointer;
  begin
    Result := zlistx_prev(FHandle);
  end;

  function TZlistx.Last: Pointer;
  begin
    Result := zlistx_last(FHandle);
  end;

  function TZlistx.Item: Pointer;
  begin
    Result := zlistx_item(FHandle);
  end;

  function TZlistx.Cursor: Pointer;
  begin
    Result := zlistx_cursor(FHandle);
  end;

  function TZlistx.Find(Item: Pointer): Pointer;
  begin
    Result := zlistx_find(FHandle, Item);
  end;

  function TZlistx.Detach(Handle: Pointer): Pointer;
  begin
    Result := zlistx_detach(FHandle, Handle);
  end;

  function TZlistx.DetachCur: Pointer;
  begin
    Result := zlistx_detach_cur(FHandle);
  end;

  function TZlistx.Delete(Handle: Pointer): Integer;
  begin
    Result := zlistx_delete(FHandle, Handle);
  end;

  procedure TZlistx.MoveStart(Handle: Pointer);
  begin
    zlistx_move_start(FHandle, Handle);
  end;

  procedure TZlistx.MoveEnd(Handle: Pointer);
  begin
    zlistx_move_end(FHandle, Handle);
  end;

  procedure TZlistx.Purge;
  begin
    zlistx_purge(FHandle);
  end;

  procedure TZlistx.Sort;
  begin
    zlistx_sort(FHandle);
  end;

  function TZlistx.Insert(Item: Pointer; LowValue: Boolean): Pointer;
  begin
    Result := zlistx_insert(FHandle, Item, LowValue);
  end;

  procedure TZlistx.Reorder(Handle: Pointer; LowValue: Boolean);
  begin
    zlistx_reorder(FHandle, Handle, LowValue);
  end;

  function TZlistx.Dup: IZlistx;
  begin
    Result := TZlistx.Wrap(zlistx_dup(FHandle), false);
  end;

  procedure TZlistx.SetDestructor(&Destructor: TZlistxDestructorFn);
  begin
    zlistx_set_destructor(FHandle, &Destructor);
  end;

  procedure TZlistx.SetDuplicator(Duplicator: TZlistxDuplicatorFn);
  begin
    zlistx_set_duplicator(FHandle, Duplicator);
  end;

  procedure TZlistx.SetComparator(Comparator: TZlistxComparatorFn);
  begin
    zlistx_set_comparator(FHandle, Comparator);
  end;

  function TZlistx.Pack: IZframe;
  begin
    Result := TZframe.Wrap(zlistx_pack(FHandle), true);
  end;

 (* TZloop *)

  constructor TZloop.New;
  begin
    Create(zloop_new, True);
  end;

  constructor TZloop.Create(handle: PZloop; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZloop.Wrap(handle: PZloop; owned: Boolean): IZloop;
  begin
    if handle <> nil then Result := TZloop.Create(handle, owned) else Result := nil;
  end;

  class function TZloop.UnWrap(const value: IZloop): PZloop;
  begin
    if value <> nil then Result := TZloop(value).FHandle else Result := nil;
  end;

  destructor TZloop.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zloop_destroy(FHandle);
  end;

  class procedure TZloop.Test(Verbose: Boolean);
  begin
    zloop_test(Verbose);
  end;

  function TZloop.Reader(const Sock: IZsock; Handler: TZloopReaderFn; Arg: Pointer): Integer;
  begin
    Result := zloop_reader(FHandle, TZsock.UnWrap(Sock), Handler, Arg);
  end;

  procedure TZloop.ReaderEnd(const Sock: IZsock);
  begin
    zloop_reader_end(FHandle, TZsock.UnWrap(Sock));
  end;

  procedure TZloop.ReaderSetTolerant(const Sock: IZsock);
  begin
    zloop_reader_set_tolerant(FHandle, TZsock.UnWrap(Sock));
  end;

  function TZloop.Poller(Item: Pointer; Handler: TZloopFn; Arg: Pointer): Integer;
  begin
    Result := zloop_poller(FHandle, Item, Handler, Arg);
  end;

  procedure TZloop.PollerEnd(Item: Pointer);
  begin
    zloop_poller_end(FHandle, Item);
  end;

  procedure TZloop.PollerSetTolerant(Item: Pointer);
  begin
    zloop_poller_set_tolerant(FHandle, Item);
  end;

  function TZloop.Timer(Delay: NativeUInt; Times: NativeUInt; Handler: TZloopTimerFn; Arg: Pointer): Integer;
  begin
    Result := zloop_timer(FHandle, Delay, Times, Handler, Arg);
  end;

  function TZloop.TimerEnd(TimerId: Integer): Integer;
  begin
    Result := zloop_timer_end(FHandle, TimerId);
  end;

  function TZloop.Ticket(Handler: TZloopTimerFn; Arg: Pointer): Pointer;
  begin
    Result := zloop_ticket(FHandle, Handler, Arg);
  end;

  procedure TZloop.TicketReset(Handle: Pointer);
  begin
    zloop_ticket_reset(FHandle, Handle);
  end;

  procedure TZloop.TicketDelete(Handle: Pointer);
  begin
    zloop_ticket_delete(FHandle, Handle);
  end;

  procedure TZloop.SetTicketDelay(TicketDelay: NativeUInt);
  begin
    zloop_set_ticket_delay(FHandle, TicketDelay);
  end;

  procedure TZloop.SetMaxTimers(MaxTimers: NativeUInt);
  begin
    zloop_set_max_timers(FHandle, MaxTimers);
  end;

  procedure TZloop.SetVerbose(Verbose: Boolean);
  begin
    zloop_set_verbose(FHandle, Verbose);
  end;

  procedure TZloop.SetNonstop(Nonstop: Boolean);
  begin
    zloop_set_nonstop(FHandle, Nonstop);
  end;

  function TZloop.Start: Integer;
  begin
    Result := zloop_start(FHandle);
  end;

 (* TZmsg *)

  constructor TZmsg.New;
  begin
    Create(zmsg_new, True);
  end;

  constructor TZmsg.Recv(const Source: IZSock);
  begin
    Create(zmsg_recv(TZsock.UnWrap(Source)), True);
  end;

  constructor TZmsg.Load(&File: Pointer);
  begin
    Create(zmsg_load(&File), True);
  end;

  constructor TZmsg.Decode(const Frame: IZframe);
  begin
    Create(zmsg_decode(TZframe.UnWrap(Frame)), True);
  end;

  constructor TZmsg.NewSignal(Status: Byte);
  begin
    Create(zmsg_new_signal(Status), True);
  end;

  constructor TZmsg.Create(handle: PZmsg; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZmsg.Wrap(handle: PZmsg; owned: Boolean): IZmsg;
  begin
    if handle <> nil then Result := TZmsg.Create(handle, owned) else Result := nil;
  end;

  class function TZmsg.UnWrap(const value: IZmsg): PZmsg;
  begin
    if value <> nil then Result := TZmsg(value).FHandle else Result := nil;
  end;

  destructor TZmsg.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zmsg_destroy(FHandle);
  end;

  class function TZmsg.Send(var SelfP: IZmsg; const Dest: IZSock): Integer;
  begin
    Result := zmsg_send(TZmsg(SelfP).FHandle, TZsock.UnWrap(Dest));
    if TZmsg(SelfP).FHandle = nil then
      SelfP := nil;
  end;

  class function TZmsg.Sendm(var SelfP: IZmsg; const Dest: IZSock): Integer;
  begin
    Result := zmsg_sendm(TZmsg(SelfP).FHandle, TZsock.UnWrap(Dest));
    if TZmsg(SelfP).FHandle = nil then
      SelfP := nil;
  end;

  class function TZmsg.&Is(This: Pointer): Boolean;
  begin
    Result := zmsg_is(This);
  end;

  class procedure TZmsg.Test(Verbose: Boolean);
  begin
    zmsg_test(Verbose);
  end;

  function TZmsg.Size: NativeUInt;
  begin
    Result := zmsg_size(FHandle);
  end;

  function TZmsg.ContentSize: NativeUInt;
  begin
    Result := zmsg_content_size(FHandle);
  end;

  function TZmsg.RoutingId: Cardinal;
  begin
    Result := zmsg_routing_id(FHandle);
  end;

  procedure TZmsg.SetRoutingId(RoutingId: Cardinal);
  begin
    zmsg_set_routing_id(FHandle, RoutingId);
  end;

  function TZmsg.Prepend(var FrameP: IZframe): Integer;
  begin
    Result := zmsg_prepend(FHandle, TZframe(FrameP).FHandle);
    if TZframe(FrameP).FHandle = nil then
      FrameP := nil;
  end;

  function TZmsg.Append(var FrameP: IZframe): Integer;
  begin
    Result := zmsg_append(FHandle, TZframe(FrameP).FHandle);
    if TZframe(FrameP).FHandle = nil then
      FrameP := nil;
  end;

  function TZmsg.Pop: IZframe;
  begin
    Result := TZframe.Wrap(zmsg_pop(FHandle), true);
  end;

  function TZmsg.Pushmem(Data: PByte; Size: NativeUInt): Integer;
  begin
    Result := zmsg_pushmem(FHandle, Data, Size);
  end;

  function TZmsg.Addmem(Data: PByte; Size: NativeUInt): Integer;
  begin
    Result := zmsg_addmem(FHandle, Data, Size);
  end;

  function TZmsg.Pushstr(const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zmsg_pushstr(FHandle, PAnsiChar(__String__));
  end;

  function TZmsg.Addstr(const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zmsg_addstr(FHandle, PAnsiChar(__String__));
  end;

  function TZmsg.Pushstrf(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zmsg_pushstrf(FHandle, PAnsiChar(__Format__));
  end;

  function TZmsg.Addstrf(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zmsg_addstrf(FHandle, PAnsiChar(__Format__));
  end;

  function TZmsg.Popstr: string;
  begin
    Result := ZFreeString(zmsg_popstr(FHandle));
  end;

  function TZmsg.Addmsg(var MsgP: IZmsg): Integer;
  begin
    Result := zmsg_addmsg(FHandle, TZmsg(MsgP).FHandle);
    if TZmsg(MsgP).FHandle = nil then
      MsgP := nil;
  end;

  function TZmsg.Popmsg: IZmsg;
  begin
    Result := TZmsg.Wrap(zmsg_popmsg(FHandle), true);
  end;

  procedure TZmsg.Remove(const Frame: IZframe);
  begin
    zmsg_remove(FHandle, TZframe.UnWrap(Frame));
  end;

  function TZmsg.First: IZframe;
  begin
    Result := TZframe.Wrap(zmsg_first(FHandle), false);
  end;

  function TZmsg.Next: IZframe;
  begin
    Result := TZframe.Wrap(zmsg_next(FHandle), false);
  end;

  function TZmsg.Last: IZframe;
  begin
    Result := TZframe.Wrap(zmsg_last(FHandle), false);
  end;

  function TZmsg.Save(&File: Pointer): Integer;
  begin
    Result := zmsg_save(FHandle, &File);
  end;

  function TZmsg.Encode: IZframe;
  begin
    Result := TZframe.Wrap(zmsg_encode(FHandle), true);
  end;

  function TZmsg.Dup: IZmsg;
  begin
    Result := TZmsg.Wrap(zmsg_dup(FHandle), true);
  end;

  procedure TZmsg.Print;
  begin
    zmsg_print(FHandle);
  end;

  function TZmsg.Eq(const Other: IZmsg): Boolean;
  begin
    Result := zmsg_eq(FHandle, TZmsg.UnWrap(Other));
  end;

  function TZmsg.Signal: Integer;
  begin
    Result := zmsg_signal(FHandle);
  end;

 (* TZpoller *)

  constructor TZpoller.New(const Reader: IZSock);
  begin
    Create(zpoller_new(TZsock.UnWrap(Reader)), True);
  end;

  constructor TZpoller.Create(handle: PZpoller; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZpoller.Wrap(handle: PZpoller; owned: Boolean): IZpoller;
  begin
    if handle <> nil then Result := TZpoller.Create(handle, owned) else Result := nil;
  end;

  class function TZpoller.UnWrap(const value: IZpoller): PZpoller;
  begin
    if value <> nil then Result := TZpoller(value).FHandle else Result := nil;
  end;

  destructor TZpoller.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zpoller_destroy(FHandle);
  end;

  class procedure TZpoller.Test(Verbose: Boolean);
  begin
    zpoller_test(Verbose);
  end;

  function TZpoller.Add(const Reader: IZSock): Integer;
  begin
    Result := zpoller_add(FHandle, TZsock.UnWrap(Reader));
  end;

  function TZpoller.Remove(Reader: Pointer): Integer;
  begin
    Result := zpoller_remove(FHandle, Reader);
  end;

  procedure TZpoller.SetNonstop(Nonstop: Boolean);
  begin
    zpoller_set_nonstop(FHandle, Nonstop);
  end;

  function TZpoller.Wait(Timeout: Integer): IZSock;
  begin
    Result := TZsock.Wrap(zpoller_wait(FHandle, Timeout), false);
  end;

  function TZpoller.Expired: Boolean;
  begin
    Result := zpoller_expired(FHandle);
  end;

  function TZpoller.Terminated: Boolean;
  begin
    Result := zpoller_terminated(FHandle);
  end;

 (* TZsock *)

  constructor TZsock.New(&Type: Integer);
  begin
    Create(zsock_new(&Type), True);
  end;

  constructor TZsock.NewPub(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_pub(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewSub(const Endpoint: string; const Subscribe: string);
  var
    __Endpoint__: UTF8String;
    __Subscribe__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    __Subscribe__ := UTF8String(Subscribe);
    Create(zsock_new_sub(PAnsiChar(__Endpoint__), PAnsiChar(__Subscribe__)), True);
  end;

  constructor TZsock.NewReq(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_req(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewRep(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_rep(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewDealer(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_dealer(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewRouter(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_router(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewPush(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_push(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewPull(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_pull(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewXpub(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_xpub(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewXsub(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_xsub(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewPair(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_pair(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewStream(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_stream(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewServer(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_server(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewClient(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_client(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewRadio(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_radio(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewDish(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_dish(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewGather(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_gather(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.NewScatter(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    Create(zsock_new_scatter(PAnsiChar(__Endpoint__)), True);
  end;

  constructor TZsock.Create(handle: PZsock; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZsock.Wrap(handle: PZsock; owned: Boolean): IZsock;
  begin
    if handle <> nil then Result := TZsock.Create(handle, owned) else Result := nil;
  end;

  class function TZsock.UnWrap(const value: IZsock): PZsock;
  begin
    if value <> nil then Result := TZsock(value).FHandle else Result := nil;
  end;

  destructor TZsock.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zsock_destroy(FHandle);
  end;

  class function TZsock.&Is(This: Pointer): Boolean;
  begin
    Result := zsock_is(This);
  end;

  class function TZsock.Resolve(This: Pointer): Pointer;
  begin
    Result := zsock_resolve(This);
  end;

  class procedure TZsock.Test(Verbose: Boolean);
  begin
    zsock_test(Verbose);
  end;

  function TZsock.Bind(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zsock_bind(FHandle, PAnsiChar(__Format__));
  end;

  function TZsock.Endpoint: string;
  begin
    Result := string(UTF8String(zsock_endpoint(FHandle)));
  end;

  function TZsock.Unbind(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zsock_unbind(FHandle, PAnsiChar(__Format__));
  end;

  function TZsock.Connect(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zsock_connect(FHandle, PAnsiChar(__Format__));
  end;

  function TZsock.Disconnect(const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zsock_disconnect(FHandle, PAnsiChar(__Format__));
  end;

  function TZsock.Attach(const Endpoints: string; Serverish: Boolean): Integer;
  var
    __Endpoints__: UTF8String;
  begin
    __Endpoints__ := UTF8String(Endpoints);
    Result := zsock_attach(FHandle, PAnsiChar(__Endpoints__), Serverish);
  end;

  function TZsock.TypeStr: string;
  begin
    Result := string(UTF8String(zsock_type_str(FHandle)));
  end;

  function TZsock.Send(const Picture: string): Integer;
  var
    __Picture__: UTF8String;
  begin
    __Picture__ := UTF8String(Picture);
    Result := zsock_send(FHandle, PAnsiChar(__Picture__));
  end;

  function TZsock.Vsend(const Picture: string; Argptr: va_list): Integer;
  var
    __Picture__: UTF8String;
  begin
    __Picture__ := UTF8String(Picture);
    Result := zsock_vsend(FHandle, PAnsiChar(__Picture__), Argptr);
  end;

  function TZsock.Recv(const Picture: string): Integer;
  var
    __Picture__: UTF8String;
  begin
    __Picture__ := UTF8String(Picture);
    Result := zsock_recv(FHandle, PAnsiChar(__Picture__));
  end;

  function TZsock.Vrecv(const Picture: string; Argptr: va_list): Integer;
  var
    __Picture__: UTF8String;
  begin
    __Picture__ := UTF8String(Picture);
    Result := zsock_vrecv(FHandle, PAnsiChar(__Picture__), Argptr);
  end;

  function TZsock.Bsend(const Picture: string): Integer;
  var
    __Picture__: UTF8String;
  begin
    __Picture__ := UTF8String(Picture);
    Result := zsock_bsend(FHandle, PAnsiChar(__Picture__));
  end;

  function TZsock.Brecv(const Picture: string): Integer;
  var
    __Picture__: UTF8String;
  begin
    __Picture__ := UTF8String(Picture);
    Result := zsock_brecv(FHandle, PAnsiChar(__Picture__));
  end;

  function TZsock.RoutingId: Cardinal;
  begin
    Result := zsock_routing_id(FHandle);
  end;

  procedure TZsock.SetRoutingId(RoutingId: Cardinal);
  begin
    zsock_set_routing_id(FHandle, RoutingId);
  end;

  procedure TZsock.SetUnbounded;
  begin
    zsock_set_unbounded(FHandle);
  end;

  function TZsock.Signal(Status: Byte): Integer;
  begin
    Result := zsock_signal(FHandle, Status);
  end;

  function TZsock.Wait: Integer;
  begin
    Result := zsock_wait(FHandle);
  end;

  procedure TZsock.Flush;
  begin
    zsock_flush(FHandle);
  end;

  function TZsock.Join(const Group: string): Integer;
  var
    __Group__: UTF8String;
  begin
    __Group__ := UTF8String(Group);
    Result := zsock_join(FHandle, PAnsiChar(__Group__));
  end;

  function TZsock.Leave(const Group: string): Integer;
  var
    __Group__: UTF8String;
  begin
    __Group__ := UTF8String(Group);
    Result := zsock_leave(FHandle, PAnsiChar(__Group__));
  end;

  function TZsock.HasIn: Boolean;
  begin
    Result := zsock_has_in(FHandle);
  end;

  function TZsock.RouterNotify: Integer;
  begin
    Result := zsock_router_notify(FHandle);
  end;

  procedure TZsock.SetRouterNotify(RouterNotify: Integer);
  begin
    zsock_set_router_notify(FHandle, RouterNotify);
  end;

  function TZsock.MulticastLoop: Integer;
  begin
    Result := zsock_multicast_loop(FHandle);
  end;

  procedure TZsock.SetMulticastLoop(MulticastLoop: Integer);
  begin
    zsock_set_multicast_loop(FHandle, MulticastLoop);
  end;

  function TZsock.Metadata: string;
  begin
    Result := ZFreeString(zsock_metadata(FHandle));
  end;

  procedure TZsock.SetMetadata(const Metadata: string);
  var
    __Metadata__: UTF8String;
  begin
    __Metadata__ := UTF8String(Metadata);
    zsock_set_metadata(FHandle, PAnsiChar(__Metadata__));
  end;

  function TZsock.LoopbackFastpath: Integer;
  begin
    Result := zsock_loopback_fastpath(FHandle);
  end;

  procedure TZsock.SetLoopbackFastpath(LoopbackFastpath: Integer);
  begin
    zsock_set_loopback_fastpath(FHandle, LoopbackFastpath);
  end;

  function TZsock.ZapEnforceDomain: Integer;
  begin
    Result := zsock_zap_enforce_domain(FHandle);
  end;

  procedure TZsock.SetZapEnforceDomain(ZapEnforceDomain: Integer);
  begin
    zsock_set_zap_enforce_domain(FHandle, ZapEnforceDomain);
  end;

  function TZsock.GssapiPrincipalNametype: Integer;
  begin
    Result := zsock_gssapi_principal_nametype(FHandle);
  end;

  procedure TZsock.SetGssapiPrincipalNametype(GssapiPrincipalNametype: Integer);
  begin
    zsock_set_gssapi_principal_nametype(FHandle, GssapiPrincipalNametype);
  end;

  function TZsock.GssapiServicePrincipalNametype: Integer;
  begin
    Result := zsock_gssapi_service_principal_nametype(FHandle);
  end;

  procedure TZsock.SetGssapiServicePrincipalNametype(GssapiServicePrincipalNametype: Integer);
  begin
    zsock_set_gssapi_service_principal_nametype(FHandle, GssapiServicePrincipalNametype);
  end;

  function TZsock.Bindtodevice: string;
  begin
    Result := ZFreeString(zsock_bindtodevice(FHandle));
  end;

  procedure TZsock.SetBindtodevice(const Bindtodevice: string);
  var
    __Bindtodevice__: UTF8String;
  begin
    __Bindtodevice__ := UTF8String(Bindtodevice);
    zsock_set_bindtodevice(FHandle, PAnsiChar(__Bindtodevice__));
  end;

  function TZsock.HeartbeatIvl: Integer;
  begin
    Result := zsock_heartbeat_ivl(FHandle);
  end;

  procedure TZsock.SetHeartbeatIvl(HeartbeatIvl: Integer);
  begin
    zsock_set_heartbeat_ivl(FHandle, HeartbeatIvl);
  end;

  function TZsock.HeartbeatTtl: Integer;
  begin
    Result := zsock_heartbeat_ttl(FHandle);
  end;

  procedure TZsock.SetHeartbeatTtl(HeartbeatTtl: Integer);
  begin
    zsock_set_heartbeat_ttl(FHandle, HeartbeatTtl);
  end;

  function TZsock.HeartbeatTimeout: Integer;
  begin
    Result := zsock_heartbeat_timeout(FHandle);
  end;

  procedure TZsock.SetHeartbeatTimeout(HeartbeatTimeout: Integer);
  begin
    zsock_set_heartbeat_timeout(FHandle, HeartbeatTimeout);
  end;

  function TZsock.UseFd: Integer;
  begin
    Result := zsock_use_fd(FHandle);
  end;

  procedure TZsock.SetUseFd(UseFd: Integer);
  begin
    zsock_set_use_fd(FHandle, UseFd);
  end;

  procedure TZsock.SetXpubManual(XpubManual: Integer);
  begin
    zsock_set_xpub_manual(FHandle, XpubManual);
  end;

  procedure TZsock.SetXpubWelcomeMsg(const XpubWelcomeMsg: string);
  var
    __XpubWelcomeMsg__: UTF8String;
  begin
    __XpubWelcomeMsg__ := UTF8String(XpubWelcomeMsg);
    zsock_set_xpub_welcome_msg(FHandle, PAnsiChar(__XpubWelcomeMsg__));
  end;

  procedure TZsock.SetStreamNotify(StreamNotify: Integer);
  begin
    zsock_set_stream_notify(FHandle, StreamNotify);
  end;

  function TZsock.InvertMatching: Integer;
  begin
    Result := zsock_invert_matching(FHandle);
  end;

  procedure TZsock.SetInvertMatching(InvertMatching: Integer);
  begin
    zsock_set_invert_matching(FHandle, InvertMatching);
  end;

  procedure TZsock.SetXpubVerboser(XpubVerboser: Integer);
  begin
    zsock_set_xpub_verboser(FHandle, XpubVerboser);
  end;

  function TZsock.ConnectTimeout: Integer;
  begin
    Result := zsock_connect_timeout(FHandle);
  end;

  procedure TZsock.SetConnectTimeout(ConnectTimeout: Integer);
  begin
    zsock_set_connect_timeout(FHandle, ConnectTimeout);
  end;

  function TZsock.TcpMaxrt: Integer;
  begin
    Result := zsock_tcp_maxrt(FHandle);
  end;

  procedure TZsock.SetTcpMaxrt(TcpMaxrt: Integer);
  begin
    zsock_set_tcp_maxrt(FHandle, TcpMaxrt);
  end;

  function TZsock.ThreadSafe: Integer;
  begin
    Result := zsock_thread_safe(FHandle);
  end;

  function TZsock.MulticastMaxtpdu: Integer;
  begin
    Result := zsock_multicast_maxtpdu(FHandle);
  end;

  procedure TZsock.SetMulticastMaxtpdu(MulticastMaxtpdu: Integer);
  begin
    zsock_set_multicast_maxtpdu(FHandle, MulticastMaxtpdu);
  end;

  function TZsock.VmciBufferSize: Integer;
  begin
    Result := zsock_vmci_buffer_size(FHandle);
  end;

  procedure TZsock.SetVmciBufferSize(VmciBufferSize: Integer);
  begin
    zsock_set_vmci_buffer_size(FHandle, VmciBufferSize);
  end;

  function TZsock.VmciBufferMinSize: Integer;
  begin
    Result := zsock_vmci_buffer_min_size(FHandle);
  end;

  procedure TZsock.SetVmciBufferMinSize(VmciBufferMinSize: Integer);
  begin
    zsock_set_vmci_buffer_min_size(FHandle, VmciBufferMinSize);
  end;

  function TZsock.VmciBufferMaxSize: Integer;
  begin
    Result := zsock_vmci_buffer_max_size(FHandle);
  end;

  procedure TZsock.SetVmciBufferMaxSize(VmciBufferMaxSize: Integer);
  begin
    zsock_set_vmci_buffer_max_size(FHandle, VmciBufferMaxSize);
  end;

  function TZsock.VmciConnectTimeout: Integer;
  begin
    Result := zsock_vmci_connect_timeout(FHandle);
  end;

  procedure TZsock.SetVmciConnectTimeout(VmciConnectTimeout: Integer);
  begin
    zsock_set_vmci_connect_timeout(FHandle, VmciConnectTimeout);
  end;

  function TZsock.Tos: Integer;
  begin
    Result := zsock_tos(FHandle);
  end;

  procedure TZsock.SetTos(Tos: Integer);
  begin
    zsock_set_tos(FHandle, Tos);
  end;

  procedure TZsock.SetRouterHandover(RouterHandover: Integer);
  begin
    zsock_set_router_handover(FHandle, RouterHandover);
  end;

  procedure TZsock.SetConnectRid(const ConnectRid: string);
  var
    __ConnectRid__: UTF8String;
  begin
    __ConnectRid__ := UTF8String(ConnectRid);
    zsock_set_connect_rid(FHandle, PAnsiChar(__ConnectRid__));
  end;

  procedure TZsock.SetConnectRidBin(ConnectRid: PByte);
  begin
    zsock_set_connect_rid_bin(FHandle, ConnectRid);
  end;

  function TZsock.HandshakeIvl: Integer;
  begin
    Result := zsock_handshake_ivl(FHandle);
  end;

  procedure TZsock.SetHandshakeIvl(HandshakeIvl: Integer);
  begin
    zsock_set_handshake_ivl(FHandle, HandshakeIvl);
  end;

  function TZsock.SocksProxy: string;
  begin
    Result := ZFreeString(zsock_socks_proxy(FHandle));
  end;

  procedure TZsock.SetSocksProxy(const SocksProxy: string);
  var
    __SocksProxy__: UTF8String;
  begin
    __SocksProxy__ := UTF8String(SocksProxy);
    zsock_set_socks_proxy(FHandle, PAnsiChar(__SocksProxy__));
  end;

  procedure TZsock.SetXpubNodrop(XpubNodrop: Integer);
  begin
    zsock_set_xpub_nodrop(FHandle, XpubNodrop);
  end;

  procedure TZsock.SetRouterMandatory(RouterMandatory: Integer);
  begin
    zsock_set_router_mandatory(FHandle, RouterMandatory);
  end;

  procedure TZsock.SetProbeRouter(ProbeRouter: Integer);
  begin
    zsock_set_probe_router(FHandle, ProbeRouter);
  end;

  procedure TZsock.SetReqRelaxed(ReqRelaxed: Integer);
  begin
    zsock_set_req_relaxed(FHandle, ReqRelaxed);
  end;

  procedure TZsock.SetReqCorrelate(ReqCorrelate: Integer);
  begin
    zsock_set_req_correlate(FHandle, ReqCorrelate);
  end;

  procedure TZsock.SetConflate(Conflate: Integer);
  begin
    zsock_set_conflate(FHandle, Conflate);
  end;

  function TZsock.ZapDomain: string;
  begin
    Result := ZFreeString(zsock_zap_domain(FHandle));
  end;

  procedure TZsock.SetZapDomain(const ZapDomain: string);
  var
    __ZapDomain__: UTF8String;
  begin
    __ZapDomain__ := UTF8String(ZapDomain);
    zsock_set_zap_domain(FHandle, PAnsiChar(__ZapDomain__));
  end;

  function TZsock.Mechanism: Integer;
  begin
    Result := zsock_mechanism(FHandle);
  end;

  function TZsock.PlainServer: Integer;
  begin
    Result := zsock_plain_server(FHandle);
  end;

  procedure TZsock.SetPlainServer(PlainServer: Integer);
  begin
    zsock_set_plain_server(FHandle, PlainServer);
  end;

  function TZsock.PlainUsername: string;
  begin
    Result := ZFreeString(zsock_plain_username(FHandle));
  end;

  procedure TZsock.SetPlainUsername(const PlainUsername: string);
  var
    __PlainUsername__: UTF8String;
  begin
    __PlainUsername__ := UTF8String(PlainUsername);
    zsock_set_plain_username(FHandle, PAnsiChar(__PlainUsername__));
  end;

  function TZsock.PlainPassword: string;
  begin
    Result := ZFreeString(zsock_plain_password(FHandle));
  end;

  procedure TZsock.SetPlainPassword(const PlainPassword: string);
  var
    __PlainPassword__: UTF8String;
  begin
    __PlainPassword__ := UTF8String(PlainPassword);
    zsock_set_plain_password(FHandle, PAnsiChar(__PlainPassword__));
  end;

  function TZsock.CurveServer: Integer;
  begin
    Result := zsock_curve_server(FHandle);
  end;

  procedure TZsock.SetCurveServer(CurveServer: Integer);
  begin
    zsock_set_curve_server(FHandle, CurveServer);
  end;

  function TZsock.CurvePublickey: string;
  begin
    Result := ZFreeString(zsock_curve_publickey(FHandle));
  end;

  procedure TZsock.SetCurvePublickey(const CurvePublickey: string);
  var
    __CurvePublickey__: UTF8String;
  begin
    __CurvePublickey__ := UTF8String(CurvePublickey);
    zsock_set_curve_publickey(FHandle, PAnsiChar(__CurvePublickey__));
  end;

  procedure TZsock.SetCurvePublickeyBin(CurvePublickey: PByte);
  begin
    zsock_set_curve_publickey_bin(FHandle, CurvePublickey);
  end;

  function TZsock.CurveSecretkey: string;
  begin
    Result := ZFreeString(zsock_curve_secretkey(FHandle));
  end;

  procedure TZsock.SetCurveSecretkey(const CurveSecretkey: string);
  var
    __CurveSecretkey__: UTF8String;
  begin
    __CurveSecretkey__ := UTF8String(CurveSecretkey);
    zsock_set_curve_secretkey(FHandle, PAnsiChar(__CurveSecretkey__));
  end;

  procedure TZsock.SetCurveSecretkeyBin(CurveSecretkey: PByte);
  begin
    zsock_set_curve_secretkey_bin(FHandle, CurveSecretkey);
  end;

  function TZsock.CurveServerkey: string;
  begin
    Result := ZFreeString(zsock_curve_serverkey(FHandle));
  end;

  procedure TZsock.SetCurveServerkey(const CurveServerkey: string);
  var
    __CurveServerkey__: UTF8String;
  begin
    __CurveServerkey__ := UTF8String(CurveServerkey);
    zsock_set_curve_serverkey(FHandle, PAnsiChar(__CurveServerkey__));
  end;

  procedure TZsock.SetCurveServerkeyBin(CurveServerkey: PByte);
  begin
    zsock_set_curve_serverkey_bin(FHandle, CurveServerkey);
  end;

  function TZsock.GssapiServer: Integer;
  begin
    Result := zsock_gssapi_server(FHandle);
  end;

  procedure TZsock.SetGssapiServer(GssapiServer: Integer);
  begin
    zsock_set_gssapi_server(FHandle, GssapiServer);
  end;

  function TZsock.GssapiPlaintext: Integer;
  begin
    Result := zsock_gssapi_plaintext(FHandle);
  end;

  procedure TZsock.SetGssapiPlaintext(GssapiPlaintext: Integer);
  begin
    zsock_set_gssapi_plaintext(FHandle, GssapiPlaintext);
  end;

  function TZsock.GssapiPrincipal: string;
  begin
    Result := ZFreeString(zsock_gssapi_principal(FHandle));
  end;

  procedure TZsock.SetGssapiPrincipal(const GssapiPrincipal: string);
  var
    __GssapiPrincipal__: UTF8String;
  begin
    __GssapiPrincipal__ := UTF8String(GssapiPrincipal);
    zsock_set_gssapi_principal(FHandle, PAnsiChar(__GssapiPrincipal__));
  end;

  function TZsock.GssapiServicePrincipal: string;
  begin
    Result := ZFreeString(zsock_gssapi_service_principal(FHandle));
  end;

  procedure TZsock.SetGssapiServicePrincipal(const GssapiServicePrincipal: string);
  var
    __GssapiServicePrincipal__: UTF8String;
  begin
    __GssapiServicePrincipal__ := UTF8String(GssapiServicePrincipal);
    zsock_set_gssapi_service_principal(FHandle, PAnsiChar(__GssapiServicePrincipal__));
  end;

  function TZsock.Ipv6: Integer;
  begin
    Result := zsock_ipv6(FHandle);
  end;

  procedure TZsock.SetIpv6(Ipv6: Integer);
  begin
    zsock_set_ipv6(FHandle, Ipv6);
  end;

  function TZsock.Immediate: Integer;
  begin
    Result := zsock_immediate(FHandle);
  end;

  procedure TZsock.SetImmediate(Immediate: Integer);
  begin
    zsock_set_immediate(FHandle, Immediate);
  end;

  function TZsock.Sndhwm: Integer;
  begin
    Result := zsock_sndhwm(FHandle);
  end;

  procedure TZsock.SetSndhwm(Sndhwm: Integer);
  begin
    zsock_set_sndhwm(FHandle, Sndhwm);
  end;

  function TZsock.Rcvhwm: Integer;
  begin
    Result := zsock_rcvhwm(FHandle);
  end;

  procedure TZsock.SetRcvhwm(Rcvhwm: Integer);
  begin
    zsock_set_rcvhwm(FHandle, Rcvhwm);
  end;

  function TZsock.Maxmsgsize: Integer;
  begin
    Result := zsock_maxmsgsize(FHandle);
  end;

  procedure TZsock.SetMaxmsgsize(Maxmsgsize: Integer);
  begin
    zsock_set_maxmsgsize(FHandle, Maxmsgsize);
  end;

  function TZsock.MulticastHops: Integer;
  begin
    Result := zsock_multicast_hops(FHandle);
  end;

  procedure TZsock.SetMulticastHops(MulticastHops: Integer);
  begin
    zsock_set_multicast_hops(FHandle, MulticastHops);
  end;

  procedure TZsock.SetXpubVerbose(XpubVerbose: Integer);
  begin
    zsock_set_xpub_verbose(FHandle, XpubVerbose);
  end;

  function TZsock.TcpKeepalive: Integer;
  begin
    Result := zsock_tcp_keepalive(FHandle);
  end;

  procedure TZsock.SetTcpKeepalive(TcpKeepalive: Integer);
  begin
    zsock_set_tcp_keepalive(FHandle, TcpKeepalive);
  end;

  function TZsock.TcpKeepaliveIdle: Integer;
  begin
    Result := zsock_tcp_keepalive_idle(FHandle);
  end;

  procedure TZsock.SetTcpKeepaliveIdle(TcpKeepaliveIdle: Integer);
  begin
    zsock_set_tcp_keepalive_idle(FHandle, TcpKeepaliveIdle);
  end;

  function TZsock.TcpKeepaliveCnt: Integer;
  begin
    Result := zsock_tcp_keepalive_cnt(FHandle);
  end;

  procedure TZsock.SetTcpKeepaliveCnt(TcpKeepaliveCnt: Integer);
  begin
    zsock_set_tcp_keepalive_cnt(FHandle, TcpKeepaliveCnt);
  end;

  function TZsock.TcpKeepaliveIntvl: Integer;
  begin
    Result := zsock_tcp_keepalive_intvl(FHandle);
  end;

  procedure TZsock.SetTcpKeepaliveIntvl(TcpKeepaliveIntvl: Integer);
  begin
    zsock_set_tcp_keepalive_intvl(FHandle, TcpKeepaliveIntvl);
  end;

  function TZsock.TcpAcceptFilter: string;
  begin
    Result := ZFreeString(zsock_tcp_accept_filter(FHandle));
  end;

  procedure TZsock.SetTcpAcceptFilter(const TcpAcceptFilter: string);
  var
    __TcpAcceptFilter__: UTF8String;
  begin
    __TcpAcceptFilter__ := UTF8String(TcpAcceptFilter);
    zsock_set_tcp_accept_filter(FHandle, PAnsiChar(__TcpAcceptFilter__));
  end;

  function TZsock.LastEndpoint: string;
  begin
    Result := ZFreeString(zsock_last_endpoint(FHandle));
  end;

  procedure TZsock.SetRouterRaw(RouterRaw: Integer);
  begin
    zsock_set_router_raw(FHandle, RouterRaw);
  end;

  function TZsock.Ipv4only: Integer;
  begin
    Result := zsock_ipv4only(FHandle);
  end;

  procedure TZsock.SetIpv4only(Ipv4only: Integer);
  begin
    zsock_set_ipv4only(FHandle, Ipv4only);
  end;

  procedure TZsock.SetDelayAttachOnConnect(DelayAttachOnConnect: Integer);
  begin
    zsock_set_delay_attach_on_connect(FHandle, DelayAttachOnConnect);
  end;

  function TZsock.Hwm: Integer;
  begin
    Result := zsock_hwm(FHandle);
  end;

  procedure TZsock.SetHwm(Hwm: Integer);
  begin
    zsock_set_hwm(FHandle, Hwm);
  end;

  function TZsock.Swap: Integer;
  begin
    Result := zsock_swap(FHandle);
  end;

  procedure TZsock.SetSwap(Swap: Integer);
  begin
    zsock_set_swap(FHandle, Swap);
  end;

  function TZsock.Affinity: Integer;
  begin
    Result := zsock_affinity(FHandle);
  end;

  procedure TZsock.SetAffinity(Affinity: Integer);
  begin
    zsock_set_affinity(FHandle, Affinity);
  end;

  function TZsock.Identity: string;
  begin
    Result := ZFreeString(zsock_identity(FHandle));
  end;

  procedure TZsock.SetIdentity(const Identity: string);
  var
    __Identity__: UTF8String;
  begin
    __Identity__ := UTF8String(Identity);
    zsock_set_identity(FHandle, PAnsiChar(__Identity__));
  end;

  function TZsock.Rate: Integer;
  begin
    Result := zsock_rate(FHandle);
  end;

  procedure TZsock.SetRate(Rate: Integer);
  begin
    zsock_set_rate(FHandle, Rate);
  end;

  function TZsock.RecoveryIvl: Integer;
  begin
    Result := zsock_recovery_ivl(FHandle);
  end;

  procedure TZsock.SetRecoveryIvl(RecoveryIvl: Integer);
  begin
    zsock_set_recovery_ivl(FHandle, RecoveryIvl);
  end;

  function TZsock.RecoveryIvlMsec: Integer;
  begin
    Result := zsock_recovery_ivl_msec(FHandle);
  end;

  procedure TZsock.SetRecoveryIvlMsec(RecoveryIvlMsec: Integer);
  begin
    zsock_set_recovery_ivl_msec(FHandle, RecoveryIvlMsec);
  end;

  function TZsock.McastLoop: Integer;
  begin
    Result := zsock_mcast_loop(FHandle);
  end;

  procedure TZsock.SetMcastLoop(McastLoop: Integer);
  begin
    zsock_set_mcast_loop(FHandle, McastLoop);
  end;

  function TZsock.Rcvtimeo: Integer;
  begin
    Result := zsock_rcvtimeo(FHandle);
  end;

  procedure TZsock.SetRcvtimeo(Rcvtimeo: Integer);
  begin
    zsock_set_rcvtimeo(FHandle, Rcvtimeo);
  end;

  function TZsock.Sndtimeo: Integer;
  begin
    Result := zsock_sndtimeo(FHandle);
  end;

  procedure TZsock.SetSndtimeo(Sndtimeo: Integer);
  begin
    zsock_set_sndtimeo(FHandle, Sndtimeo);
  end;

  function TZsock.Sndbuf: Integer;
  begin
    Result := zsock_sndbuf(FHandle);
  end;

  procedure TZsock.SetSndbuf(Sndbuf: Integer);
  begin
    zsock_set_sndbuf(FHandle, Sndbuf);
  end;

  function TZsock.Rcvbuf: Integer;
  begin
    Result := zsock_rcvbuf(FHandle);
  end;

  procedure TZsock.SetRcvbuf(Rcvbuf: Integer);
  begin
    zsock_set_rcvbuf(FHandle, Rcvbuf);
  end;

  function TZsock.Linger: Integer;
  begin
    Result := zsock_linger(FHandle);
  end;

  procedure TZsock.SetLinger(Linger: Integer);
  begin
    zsock_set_linger(FHandle, Linger);
  end;

  function TZsock.ReconnectIvl: Integer;
  begin
    Result := zsock_reconnect_ivl(FHandle);
  end;

  procedure TZsock.SetReconnectIvl(ReconnectIvl: Integer);
  begin
    zsock_set_reconnect_ivl(FHandle, ReconnectIvl);
  end;

  function TZsock.ReconnectIvlMax: Integer;
  begin
    Result := zsock_reconnect_ivl_max(FHandle);
  end;

  procedure TZsock.SetReconnectIvlMax(ReconnectIvlMax: Integer);
  begin
    zsock_set_reconnect_ivl_max(FHandle, ReconnectIvlMax);
  end;

  function TZsock.Backlog: Integer;
  begin
    Result := zsock_backlog(FHandle);
  end;

  procedure TZsock.SetBacklog(Backlog: Integer);
  begin
    zsock_set_backlog(FHandle, Backlog);
  end;

  procedure TZsock.SetSubscribe(const Subscribe: string);
  var
    __Subscribe__: UTF8String;
  begin
    __Subscribe__ := UTF8String(Subscribe);
    zsock_set_subscribe(FHandle, PAnsiChar(__Subscribe__));
  end;

  procedure TZsock.SetUnsubscribe(const Unsubscribe: string);
  var
    __Unsubscribe__: UTF8String;
  begin
    __Unsubscribe__ := UTF8String(Unsubscribe);
    zsock_set_unsubscribe(FHandle, PAnsiChar(__Unsubscribe__));
  end;

  function TZsock.&Type: Integer;
  begin
    Result := zsock_type(FHandle);
  end;

  function TZsock.Rcvmore: Integer;
  begin
    Result := zsock_rcvmore(FHandle);
  end;

  function TZsock.Fd: TSocket;
  begin
    Result := zsock_fd(FHandle);
  end;

  function TZsock.Events: Integer;
  begin
    Result := zsock_events(FHandle);
  end;

 (* TZstr *)

  class function TZstr.Recv(const Source: IZSock): string;
  begin
    Result := ZFreeString(zstr_recv(TZsock.UnWrap(Source)));
  end;

  class function TZstr.RecvCompress(const Source: IZSock): string;
  begin
    Result := ZFreeString(zstr_recv_compress(TZsock.UnWrap(Source)));
  end;

  class function TZstr.Send(const Dest: IZSock; const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zstr_send(TZsock.UnWrap(Dest), PAnsiChar(__String__));
  end;

  class function TZstr.Sendm(const Dest: IZSock; const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zstr_sendm(TZsock.UnWrap(Dest), PAnsiChar(__String__));
  end;

  class function TZstr.Sendf(const Dest: IZSock; const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zstr_sendf(TZsock.UnWrap(Dest), PAnsiChar(__Format__));
  end;

  class function TZstr.Sendfm(const Dest: IZSock; const Format: string): Integer;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := zstr_sendfm(TZsock.UnWrap(Dest), PAnsiChar(__Format__));
  end;

  class function TZstr.Sendx(const Dest: IZSock; const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zstr_sendx(TZsock.UnWrap(Dest), PAnsiChar(__String__));
  end;

  class function TZstr.SendCompress(const Dest: IZSock; const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zstr_send_compress(TZsock.UnWrap(Dest), PAnsiChar(__String__));
  end;

  class function TZstr.SendmCompress(const Dest: IZSock; const &String: string): Integer;
  var
    __String__: UTF8String;
  begin
    __String__ := UTF8String(&String);
    Result := zstr_sendm_compress(TZsock.UnWrap(Dest), PAnsiChar(__String__));
  end;

  class function TZstr.Str(const Source: IZSock): string;
  begin
    Result := ZFreeString(zstr_str(TZsock.UnWrap(Source)));
  end;

  class procedure TZstr.Test(Verbose: Boolean);
  begin
    zstr_test(Verbose);
  end;

 (* TZsys *)

  class function TZsys.Init: Pointer;
  begin
    Result := zsys_init;
  end;

  class procedure TZsys.Shutdown;
  begin
    zsys_shutdown;
  end;

  class function TZsys.Socket(&Type: Integer; const Filename: string; LineNbr: NativeUInt): Pointer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_socket(&Type, PAnsiChar(__Filename__), LineNbr);
  end;

  class function TZsys.Close(Handle: Pointer; const Filename: string; LineNbr: NativeUInt): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_close(Handle, PAnsiChar(__Filename__), LineNbr);
  end;

  class function TZsys.Sockname(Socktype: Integer): string;
  begin
    Result := string(UTF8String(zsys_sockname(Socktype)));
  end;

  class function TZsys.CreatePipe(var BackendP: IZsock): IZsock;
  begin
    Result := TZsock.Wrap(zsys_create_pipe(TZsock(BackendP).FHandle), false);
    if TZsock(BackendP).FHandle = nil then
      BackendP := nil;
  end;

  class procedure TZsys.HandlerSet(HandlerFn: PZsysHandlerFn);
  begin
    zsys_handler_set(HandlerFn);
  end;

  class procedure TZsys.HandlerReset;
  begin
    zsys_handler_reset;
  end;

  class procedure TZsys.CatchInterrupts;
  begin
    zsys_catch_interrupts;
  end;

  class function TZsys.IsInterrupted: Boolean;
  begin
    Result := zsys_is_interrupted;
  end;

  class procedure TZsys.SetInterrupted;
  begin
    zsys_set_interrupted;
  end;

  class function TZsys.FileExists(const Filename: string): Boolean;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_file_exists(PAnsiChar(__Filename__));
  end;

  class function TZsys.FileModified(const Filename: string): Int64;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_file_modified(PAnsiChar(__Filename__));
  end;

  class function TZsys.FileMode(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_file_mode(PAnsiChar(__Filename__));
  end;

  class function TZsys.FileDelete(const Filename: string): Integer;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_file_delete(PAnsiChar(__Filename__));
  end;

  class function TZsys.FileStable(const Filename: string): Boolean;
  var
    __Filename__: UTF8String;
  begin
    __Filename__ := UTF8String(Filename);
    Result := zsys_file_stable(PAnsiChar(__Filename__));
  end;

  class function TZsys.DirCreate(const Pathname: string): Integer;
  var
    __Pathname__: UTF8String;
  begin
    __Pathname__ := UTF8String(Pathname);
    Result := zsys_dir_create(PAnsiChar(__Pathname__));
  end;

  class function TZsys.DirDelete(const Pathname: string): Integer;
  var
    __Pathname__: UTF8String;
  begin
    __Pathname__ := UTF8String(Pathname);
    Result := zsys_dir_delete(PAnsiChar(__Pathname__));
  end;

  class function TZsys.DirChange(const Pathname: string): Integer;
  var
    __Pathname__: UTF8String;
  begin
    __Pathname__ := UTF8String(Pathname);
    Result := zsys_dir_change(PAnsiChar(__Pathname__));
  end;

  class procedure TZsys.FileModePrivate;
  begin
    zsys_file_mode_private;
  end;

  class procedure TZsys.FileModeDefault;
  begin
    zsys_file_mode_default;
  end;

  class procedure TZsys.Version(var Major: Integer; var Minor: Integer; var Patch: Integer);
  begin
    zsys_version(Major, Minor, Patch);
  end;

  class function TZsys.SprintfHint(Hint: Integer; const Format: string): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := string(UTF8String(zsys_sprintf_hint(Hint, PAnsiChar(__Format__))));
  end;

  class function TZsys.Sprintf(const Format: string): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := string(UTF8String(zsys_sprintf(PAnsiChar(__Format__))));
  end;

  class function TZsys.Vprintf(const Format: string; Argptr: va_list): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := string(UTF8String(zsys_vprintf(PAnsiChar(__Format__), Argptr)));
  end;

  class function TZsys.UdpNew(Routable: Boolean): TSocket;
  begin
    Result := zsys_udp_new(Routable);
  end;

  class function TZsys.UdpClose(Handle: TSocket): Integer;
  begin
    Result := zsys_udp_close(Handle);
  end;

  class function TZsys.UdpSend(Udpsock: TSocket; const Frame: IZframe; Address: Pointer; Addrlen: Integer): Integer;
  begin
    Result := zsys_udp_send(Udpsock, TZframe.UnWrap(Frame), Address, Addrlen);
  end;

  class function TZsys.UdpRecv(Udpsock: TSocket; const Peername: string; Peerlen: Integer): IZframe;
  var
    __Peername__: UTF8String;
  begin
    __Peername__ := UTF8String(Peername);
    Result := TZframe.Wrap(zsys_udp_recv(Udpsock, PAnsiChar(__Peername__), Peerlen), false);
  end;

  class procedure TZsys.SocketError(const Reason: string);
  var
    __Reason__: UTF8String;
  begin
    __Reason__ := UTF8String(Reason);
    zsys_socket_error(PAnsiChar(__Reason__));
  end;

  class function TZsys.Hostname: string;
  begin
    Result := string(UTF8String(zsys_hostname));
  end;

  class function TZsys.Daemonize(const Workdir: string): Integer;
  var
    __Workdir__: UTF8String;
  begin
    __Workdir__ := UTF8String(Workdir);
    Result := zsys_daemonize(PAnsiChar(__Workdir__));
  end;

  class function TZsys.RunAs(const Lockfile: string; const Group: string; const User: string): Integer;
  var
    __Lockfile__: UTF8String;
    __Group__: UTF8String;
    __User__: UTF8String;
  begin
    __Lockfile__ := UTF8String(Lockfile);
    __Group__ := UTF8String(Group);
    __User__ := UTF8String(User);
    Result := zsys_run_as(PAnsiChar(__Lockfile__), PAnsiChar(__Group__), PAnsiChar(__User__));
  end;

  class function TZsys.HasCurve: Boolean;
  begin
    Result := zsys_has_curve;
  end;

  class procedure TZsys.SetIoThreads(IoThreads: NativeUInt);
  begin
    zsys_set_io_threads(IoThreads);
  end;

  class procedure TZsys.SetThreadSchedPolicy(Policy: Integer);
  begin
    zsys_set_thread_sched_policy(Policy);
  end;

  class procedure TZsys.SetThreadPriority(Priority: Integer);
  begin
    zsys_set_thread_priority(Priority);
  end;

  class procedure TZsys.SetThreadNamePrefix(Prefix: Integer);
  begin
    zsys_set_thread_name_prefix(Prefix);
  end;

  class function TZsys.ThreadNamePrefix: Integer;
  begin
    Result := zsys_thread_name_prefix;
  end;

  class procedure TZsys.ThreadAffinityCpuAdd(Cpu: Integer);
  begin
    zsys_thread_affinity_cpu_add(Cpu);
  end;

  class procedure TZsys.ThreadAffinityCpuRemove(Cpu: Integer);
  begin
    zsys_thread_affinity_cpu_remove(Cpu);
  end;

  class procedure TZsys.SetMaxSockets(MaxSockets: NativeUInt);
  begin
    zsys_set_max_sockets(MaxSockets);
  end;

  class function TZsys.SocketLimit: NativeUInt;
  begin
    Result := zsys_socket_limit;
  end;

  class procedure TZsys.SetMaxMsgsz(MaxMsgsz: Integer);
  begin
    zsys_set_max_msgsz(MaxMsgsz);
  end;

  class function TZsys.MaxMsgsz: Integer;
  begin
    Result := zsys_max_msgsz;
  end;

  class procedure TZsys.SetZeroCopyRecv(ZeroCopy: Integer);
  begin
    zsys_set_zero_copy_recv(ZeroCopy);
  end;

  class function TZsys.ZeroCopyRecv: Integer;
  begin
    Result := zsys_zero_copy_recv;
  end;

  class procedure TZsys.SetFileStableAgeMsec(FileStableAgeMsec: Int64);
  begin
    zsys_set_file_stable_age_msec(FileStableAgeMsec);
  end;

  class function TZsys.FileStableAgeMsec: Int64;
  begin
    Result := zsys_file_stable_age_msec;
  end;

  class procedure TZsys.SetLinger(Linger: NativeUInt);
  begin
    zsys_set_linger(Linger);
  end;

  class procedure TZsys.SetSndhwm(Sndhwm: NativeUInt);
  begin
    zsys_set_sndhwm(Sndhwm);
  end;

  class procedure TZsys.SetRcvhwm(Rcvhwm: NativeUInt);
  begin
    zsys_set_rcvhwm(Rcvhwm);
  end;

  class procedure TZsys.SetPipehwm(Pipehwm: NativeUInt);
  begin
    zsys_set_pipehwm(Pipehwm);
  end;

  class function TZsys.Pipehwm: NativeUInt;
  begin
    Result := zsys_pipehwm;
  end;

  class procedure TZsys.SetIpv6(Ipv6: Integer);
  begin
    zsys_set_ipv6(Ipv6);
  end;

  class function TZsys.Ipv6: Integer;
  begin
    Result := zsys_ipv6;
  end;

  class procedure TZsys.SetInterface(const Value: string);
  var
    __Value__: UTF8String;
  begin
    __Value__ := UTF8String(Value);
    zsys_set_interface(PAnsiChar(__Value__));
  end;

  class function TZsys.&Interface: string;
  begin
    Result := string(UTF8String(zsys_interface));
  end;

  class procedure TZsys.SetIpv6Address(const Value: string);
  var
    __Value__: UTF8String;
  begin
    __Value__ := UTF8String(Value);
    zsys_set_ipv6_address(PAnsiChar(__Value__));
  end;

  class function TZsys.Ipv6Address: string;
  begin
    Result := string(UTF8String(zsys_ipv6_address));
  end;

  class procedure TZsys.SetIpv6McastAddress(const Value: string);
  var
    __Value__: UTF8String;
  begin
    __Value__ := UTF8String(Value);
    zsys_set_ipv6_mcast_address(PAnsiChar(__Value__));
  end;

  class function TZsys.Ipv6McastAddress: string;
  begin
    Result := string(UTF8String(zsys_ipv6_mcast_address));
  end;

  class procedure TZsys.SetAutoUseFd(AutoUseFd: Integer);
  begin
    zsys_set_auto_use_fd(AutoUseFd);
  end;

  class function TZsys.AutoUseFd: Integer;
  begin
    Result := zsys_auto_use_fd;
  end;

  class function TZsys.Zprintf(const Format: string; const Args: IZhash): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := ZFreeString(zsys_zprintf(PAnsiChar(__Format__), TZhash.UnWrap(Args)));
  end;

  class function TZsys.ZprintfError(const Format: string; const Args: IZhash): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := ZFreeString(zsys_zprintf_error(PAnsiChar(__Format__), TZhash.UnWrap(Args)));
  end;

  class function TZsys.Zplprintf(const Format: string; const Args: IZconfig): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := ZFreeString(zsys_zplprintf(PAnsiChar(__Format__), TZconfig.UnWrap(Args)));
  end;

  class function TZsys.ZplprintfError(const Format: string; const Args: IZconfig): string;
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    Result := ZFreeString(zsys_zplprintf_error(PAnsiChar(__Format__), TZconfig.UnWrap(Args)));
  end;

  class procedure TZsys.SetLogident(const Value: string);
  var
    __Value__: UTF8String;
  begin
    __Value__ := UTF8String(Value);
    zsys_set_logident(PAnsiChar(__Value__));
  end;

  class procedure TZsys.SetLogstream(Stream: Pointer);
  begin
    zsys_set_logstream(Stream);
  end;

  class procedure TZsys.SetLogsender(const Endpoint: string);
  var
    __Endpoint__: UTF8String;
  begin
    __Endpoint__ := UTF8String(Endpoint);
    zsys_set_logsender(PAnsiChar(__Endpoint__));
  end;

  class procedure TZsys.SetLogsystem(Logsystem: Boolean);
  begin
    zsys_set_logsystem(Logsystem);
  end;

  class procedure TZsys.Error(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zsys_error(PAnsiChar(__Format__));
  end;

  class procedure TZsys.Warning(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zsys_warning(PAnsiChar(__Format__));
  end;

  class procedure TZsys.Notice(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zsys_notice(PAnsiChar(__Format__));
  end;

  class procedure TZsys.Info(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zsys_info(PAnsiChar(__Format__));
  end;

  class procedure TZsys.Debug(const Format: string);
  var
    __Format__: UTF8String;
  begin
    __Format__ := UTF8String(Format);
    zsys_debug(PAnsiChar(__Format__));
  end;

  class procedure TZsys.Test(Verbose: Boolean);
  begin
    zsys_test(Verbose);
  end;

 (* TZuuid *)

  constructor TZuuid.New;
  begin
    Create(zuuid_new, True);
  end;

  constructor TZuuid.NewFrom(Source: PByte);
  begin
    Create(zuuid_new_from(Source), True);
  end;

  constructor TZuuid.Create(handle: PZuuid; owned: Boolean);
  begin
    FHandle := handle;
    FOwned := owned;
  end;

  class function TZuuid.Wrap(handle: PZuuid; owned: Boolean): IZuuid;
  begin
    if handle <> nil then Result := TZuuid.Create(handle, owned) else Result := nil;
  end;

  class function TZuuid.UnWrap(const value: IZuuid): PZuuid;
  begin
    if value <> nil then Result := TZuuid(value).FHandle else Result := nil;
  end;

  destructor TZuuid.Destroy;
  begin
    if FOwned and (FHandle <> nil) then
      zuuid_destroy(FHandle);
  end;

  class procedure TZuuid.Test(Verbose: Boolean);
  begin
    zuuid_test(Verbose);
  end;

  procedure TZuuid.&Set(Source: PByte);
  begin
    zuuid_set(FHandle, Source);
  end;

  function TZuuid.SetStr(const Source: string): Integer;
  var
    __Source__: UTF8String;
  begin
    __Source__ := UTF8String(Source);
    Result := zuuid_set_str(FHandle, PAnsiChar(__Source__));
  end;

  function TZuuid.Data: PByte;
  begin
    Result := zuuid_data(FHandle);
  end;

  function TZuuid.Size: NativeUInt;
  begin
    Result := zuuid_size(FHandle);
  end;

  function TZuuid.Str: string;
  begin
    Result := string(UTF8String(zuuid_str(FHandle)));
  end;

  function TZuuid.StrCanonical: string;
  begin
    Result := string(UTF8String(zuuid_str_canonical(FHandle)));
  end;

  procedure TZuuid.Export(Target: PByte);
  begin
    zuuid_export(FHandle, Target);
  end;

  function TZuuid.Eq(Compare: PByte): Boolean;
  begin
    Result := zuuid_eq(FHandle, Compare);
  end;

  function TZuuid.Neq(Compare: PByte): Boolean;
  begin
    Result := zuuid_neq(FHandle, Compare);
  end;

  function TZuuid.Dup: IZuuid;
  begin
    Result := TZuuid.Wrap(zuuid_dup(FHandle), false);
  end;

 (* TZauth *)

  class procedure TZauth.Test(Verbose: Boolean);
  begin
    zauth_test(Verbose);
  end;

 (* TZbeacon *)

  class procedure TZbeacon.Test(Verbose: Boolean);
  begin
    zbeacon_test(Verbose);
  end;

 (* TZgossip *)

  class procedure TZgossip.Test(Verbose: Boolean);
  begin
    zgossip_test(Verbose);
  end;

 (* TZmonitor *)

  class procedure TZmonitor.Test(Verbose: Boolean);
  begin
    zmonitor_test(Verbose);
  end;

 (* TZproxy *)

  class procedure TZproxy.Test(Verbose: Boolean);
  begin
    zproxy_test(Verbose);
  end;

 (* TZrex *)

  class procedure TZrex.Test(Verbose: Boolean);
  begin
    zrex_test(Verbose);
  end;
end.
