Invoke a function in the mainloop, pass the data back.

def invoke_in_mainloop(func, *args, **kwargs):
    """
    Invoke a function in the mainloop, pass the data back.
    """
    results = queue.Queue()

    @gcall
    def run():
        try:
            data = func(*args, **kwargs)
            results.put(data)
            results.put(None)
        except BaseException:  # XXX: handle
            results.put(None)
            results.put(sys.exc_info())
            raise

    data = results.get()
    exception = results.get()

    if exception is None:
        return data
    else:
        tp, val, tb = results.get()
        raise tp, val, tb