lgi-devs / lgi

Dynamic Lua binding to GObject libraries using GObject-Introspection
MIT License
440 stars 70 forks source link

Passing GType as an argument #320

Closed danilax999 closed 3 months ago

danilax999 commented 3 months ago

Hi, I'm trying to enumerate wireplumber objects via wireplumber's introspected API, but for some reason it doesn't find any.

Here is lua example:

local lgi = require('lgi')
local GLib = lgi.require('GLib', '2.0')
local Wp = lgi.require('Wp', '0.5')

Wp.init(Wp.InitFlags.ALL)
local loop = GLib.MainLoop.new(nil, false)
local core = Wp.Core.new()

local object_manager = Wp.ObjectManager.new()
local interest = Wp.ObjectInterest.new_type(Wp.Node)
object_manager:add_interest_full(interest)

function object_manager:on_installed()
  print('Installed object manager')
  object_manager:new_iterator()
      :foreach(function(obj) print('Id:', obj:get_id()) end)
  loop:quit()
end

core:install_object_manager(object_manager)
core:connect()

loop:run()

Here is an equivalent python example that works as intended:

import gi
gi.require_version('GLib', '2.0')
gi.require_version('Wp', '0.5')
from gi.repository import Wp, GLib

Wp.init(Wp.InitFlags.ALL)
loop = GLib.MainLoop.new(None, False)
core = Wp.Core.new()

object_manager = Wp.ObjectManager.new()
interest = Wp.ObjectInterest.new_type(Wp.Node)
object_manager.add_interest_full(interest)

def on_installed(om):
    print('Installed object manager')
    object_manager.new_iterator()\
                  .foreach(lambda obj: print('Id:', obj.get_id()))
    loop.quit()

object_manager.connect('installed', on_installed)

core.install_object_manager(object_manager)
core.connect()

loop.run()

My assumption is that lgi doesn't cast Wp.Node as plain GType in the line local interest = Wp.ObjectInterest.new_type(Wp.Node).

new_type function has the following signature: WpObjectInterest *wp_object_interest_new_type(GType gtype). Here is a link to Wireplumber docs.

Changing Wp.Node to Wp.Node._gtype has no effect.

psychon commented 3 months ago

Well... according to ltrace -e wp_object_interest_new_type, that function is never called. But gdb disagrees and the setpoint is hit. gdb says the argument is exactly what you want it to be:

Breakpoint 1, wp_object_interest_new_type (gtype=0x555555631690 [WpNode/WpGlobalProxy/WpProxy/WpObject]) at ../lib/wp/object-interest.c:164

Anyway, what does this program do for you? Because for me it crashes in wireplumber amd that looks like a null pointer dereference:

Program received signal SIGSEGV, Segmentation fault.
core_new (context=0x0, properties=<optimized out>, user_data_size=user_data_size@entry=0) at ../src/pipewire/core.c:321
warning: 321    ../src/pipewire/core.c: Datei oder Verzeichnis nicht gefunden
(gdb) bt
#0  core_new (context=0x0, properties=<optimized out>, user_data_size=user_data_size@entry=0) at ../src/pipewire/core.c:321
#1  0x00007ffff745542f in pw_context_connect (context=<optimized out>, properties=<optimized out>, user_data_size=user_data_size@entry=0) at ../src/pipewire/core.c:399
#2  0x00007ffff7523067 in wp_core_connect (self=0x55555563c840 [WpCore]) at ../lib/wp/core.c:877
[...]
danilax999 commented 3 months ago

For me it just prints Installed object manager, while it should also print all Node objects. Python version outputs

Installed object manager
Id: 2
Id: 3
Id: 4
Id: 5
Id: 6
Id: 7
Id: 8

I also tried to use ltrace but it doesn't show any function calls from GLib. I wasn't able to debug it with gdb. I suppose wireplumber should be compiled with debug symbols for it.

danilax999 commented 3 months ago

Does python version also crashes for you?

psychon commented 3 months ago

Yup.

danilax999 commented 3 months ago

The issue was in the object_manager:new_iterator():foreach() function. The function accepted by foreach function accepts an attribute of type GValue * and while pygobject automatically converts GValue to the intended type, lgi doesn't, so the actual value has to be accessed via value attribute:

  object_manager:new_iterator()
      :foreach(function(obj) print('Id:', obj.value:get_id()) end)
psychon commented 3 months ago

Ah, thanks for figuring this out and thanks for posting an update here. Sorry that I couldn't help here.