How to return value in Gio.Task?

Hi.
I’m trying to make a simple example on how to make custom non-blocking functions using Gio.Task and Python.

Code snippet
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gio, GLib, Gtk


def callback(obj, task, *args):

    print("Object :", obj)
    print("Result :", task.propagate_pointer()) # Error 2


def blocking_func(task, but, prompt, cancellable):

    ret = input(prompt)
    task.return_pointer(ret, None) # Error 1


def on_clicked(but):

    # We will make the text in our entry as prompt for input.
    cancellable = None # For sake of readability
    prompt = entry.get_text()
    task = Gio.Task.new(but, cancellable, callback, prompt)
    task.run_in_thread(blocking_func)


win = Gtk.Window()
entry = Gtk.Entry()
button = Gtk.Button(label="Click")

button.connect("clicked", on_clicked)

grid = Gtk.Grid()
grid.add(entry)
grid.add(button)

win.add(grid)

win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

As easy as that, the idea is to have a window with an entry bar and button. When button is clicked, it will take input from user (from terminal or console) and print it. The prompt for input should not block the GUI, so it should be an asynchronous implementation.

All went well, the app didn’t freeze while there was waiting prompt, but problem came when I needed to return the input of user.

I used task.return_pointer(ret, None) but I got error :

ValueError: Pointer arguments are restricted to integers, capsules, and None. See: https://bugzilla.gnome.org/show_bug.cgi?id=683599

(The link took me to a bug report of 2012)
Feeling broken, I tested how it works when it returns integer. So I changed the same like to : task.return_pointer(len(ret), None). Though it gave proper output but it gave me warning :

** (scratch.py:20816): WARNING **: 00:07:39.748: (gi/pygi-basictype.c:78):marshal_from_py_void: runtime check failed: (arg_cache->transfer == GI_TRANSFER_NOTHING)

What am I doing wrong? What is the proper way to return a value in Gio.Task ?

Thanks !

This issue is not solved yet. And there is a bug (or limitation) that Gio.Task can’t handle data object. For example try this in your interpreter:

>>> from gi.repository import Gio
>>> task = Gio.Task.new(None, None, print, "my-data")
>>> task.get_task_data()
0

Because it seems Gio.Task's data was based on pointers (C thing)

If you need to return an integer, why are you using Gio.Task.return_pointer(), instead of Gio.Task.return_int()?

If you need to return complex data, you will need to use Gio.Task.return_value(), which requires GLib 2.64.

Actually 100 years (in India, while talking or thinking about a person, if they come up, we say the person will live for 100 years and I thought of tagging you :smile:, okay it’s offtopic)

I didn’t want to return integer, but I just tested it because the error said it support integers.

That’s not how get_task_data() works.

The task data is not the data you pass when creating the Gio.Task instance; that’s the data that gets passed to the callback.

If you want to associate data to the Gio.Task instance, you must use Gio.Task.set_task_data(), and retrieve it using Gio.Task.get_task_data().

Never knew of return_value method, let me try it!

Update : The reason I never knew of this method is that my Devhelp didn’t mention this method at all! I checked if my local copy is update to date with the repo and yes it is. Weird again.

set_task_data returns ValueError

It supports integer literals, like 1, or 10000, or 666.

In general, return_pointer() is only for pointer-sized data that does not have memory management semantics and can be copied by value.

@ebassi from the docs and what you said, callback_data is passed to the callback function right? But I always get None as callback_data in my function. (in code I shared in question)

For example I typed >>> in the entry but I always get None for prompt in blocking_func.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.