docs: def _init_virtual_io(self, file):
          """Initialize callback functions for sf_open_virtual()."""
          @_ffi.callback("sf_vio_get_filelen")
          def vio_get_filelen(user_data):
              curr = file.tell()
              file.seek(0, SEEK_END)
              size = file.tell()
              file.seek(curr, SEEK_SET)
              return size
  
          @_ffi.callback("sf_vio_seek")
          def vio_seek(offset, whence, user_data):
              file.seek(offset, whence)
              return file.tell()
  
          @_ffi.callback("sf_vio_read")
          def vio_read(ptr, count, user_data):
              # first try readinto(), if not available fall back to read()
              try:
                  buf = _ffi.buffer(ptr, count)
                  data_read = file.readinto(buf)
              except AttributeError:
                  data = file.read(count)
                  data_read = len(data)
                  buf = _ffi.buffer(ptr, data_read)
                  buf[0:data_read] = data
              return data_read
  
          @_ffi.callback("sf_vio_write")
          def vio_write(ptr, count, user_data):
              buf = _ffi.buffer(ptr, count)
              data = buf[:]
              written = file.write(data)
              # write() returns None for file objects in Python <= 2.7:
              if written is None:
                  written = count
              return written
  
          @_ffi.callback("sf_vio_tell")
          def vio_tell(user_data):
              return file.tell()
  
          # Note: the callback functions must be kept alive!
          self._virtual_io = {'get_filelen': vio_get_filelen,
                              'seek': vio_seek,
                              'read': vio_read,
                              'write': vio_write,
                              'tell': vio_tell}
  
          return _ffi.new("SF_VIRTUAL_IO*", self._virtual_io)