Add support for user-defined unrar events

I've added RARSetCallback function to unrarlib. It allows to implement non-standard processing of data.

For example I use it to crunch uncompressed data without storing it on disk:

```python

import ctypes
import unrar.constants
from unrar import rarfile
from unrar import unrarlib

class RarFileExt(rarfile.RarFile):

    def _callback(self, msg, UserData, P1, P2):
        if msg == unrar.constants.UCM_PROCESSDATA:
            data = (ctypes.c_char*P2).from_address(P1).raw
            # PROCESS DATA HERE
        return 1

    def _unrar_file(self, filename, pwd=None):
        archive = unrarlib.RAROpenArchiveDataEx(
            self.filename, mode=unrar.constants.RAR_OM_EXTRACT)
        handle = self._open(archive)

        password = pwd or self.pwd
        if password is not None:
            unrarlib.RARSetPassword(handle, rarfile.b(password))

        try:
            rarinfo = self._read_header(handle)
            while rarinfo is not None:
                if rarinfo.filename == filename:
                    _rar_callback = unrarlib.UNRARCALLBACK(self._callback)
                    unrarlib.RARSetCallback(handle, _rar_callback, 0)
                    self._process_current(
                        handle, unrar.constants.RAR_TEST) # RAR_EXTRACT will create files, so RAR_TEST
                    unrarlib.RARSetCallback(handle, unrarlib.UNRARCALLBACK(0), 0) # clean up, just in case
                    break
                else:
                    self._process_current(handle, unrar.constants.RAR_SKIP)
                rarinfo = self._read_header(handle)
        except unrarlib.UnrarException:
            raise BadRarFile("Bad RAR archive data.")
        finally:
            self._close(handle)

```