Unable to call a gtk instance method of a derived class if there is a virtual function with the same name #303

Closed
opened 2025-11-24 15:20:52 +01:00 by Nyeksenn · 9 comments
Nyeksenn commented 2025-11-24 15:20:52 +01:00 (Migrated from github.com)

I have a class MediaSubsonic which is derived from MediaStream.
MediaStream contains both a virtual method called seek and an instance method called seek.
The instance method is the only way to set the seeking property on a MediaStream instance.
However, I also need to override the virtual method because this is how the actual work gets performed.
If i call the seek method on a MediaStream reference which points to an instance of my derived class,
Java directly calls the overridden virtual function. This way, the seeking property is never set.
I also can't call the instance method using super in the virtual method, because this leads to a loop.
Is it possible in any way to call the instance method instead of the virtual method on an instance of my derived class?

I have a class `MediaSubsonic` which is derived from `MediaStream`. `MediaStream` contains both a virtual method called `seek` and an instance method called `seek`. The instance method is the only way to set the seeking property on a `MediaStream` instance. However, I also need to override the virtual method because this is how the actual work gets performed. If i call the `seek` method on a `MediaStream` reference which points to an instance of my derived class, Java directly calls the overridden virtual function. This way, the `seeking` property is never set. I also can't call the instance method using `super` in the virtual method, because this leads to a loop. Is it possible in any way to call the instance method instead of the virtual method on an instance of my derived class?
jwharm commented 2025-11-24 17:45:42 +01:00 (Migrated from github.com)

You can call the virtual method of the parent class with asParent().seek().

You can call the virtual method of the parent class with `asParent().seek()`.
Nyeksenn commented 2025-11-24 18:16:14 +01:00 (Migrated from github.com)

Yes, but I want to call the instance method of the parent. The one that is registered on the instance struct and accessible in the derived class as super, but outside of the derived class.

Yes, but I want to call the instance method of the parent. The one that is registered on the instance struct and accessible in the derived class as super, but outside of the derived class.
Nyeksenn commented 2025-11-24 18:46:49 +01:00 (Migrated from github.com)

So I did some more experimentation.
If I instantiate MediaStream$Impl with a handle it works how I intend it to work.
However, I am not sure, whether this is the proper way to do this.

So I did some more experimentation. If I instantiate `MediaStream$Impl` with a handle it works how I intend it to work. However, I am not sure, whether this is the proper way to do this.
jwharm commented 2025-11-24 19:35:33 +01:00 (Migrated from github.com)

Huh, you’re right. The instance method sets the seeking property after the virtual method completes. That’s odd.

Huh, you’re right. The instance method sets the `seeking` property after the virtual method completes. That’s odd.
Nyeksenn commented 2025-11-24 21:31:42 +01:00 (Migrated from github.com)

I think that is by design. The virtual method is for the implementation and the instance method for the caller. That just doesn't map well to Java

I think that is by design. The virtual method is for the implementation and the instance method for the caller. That just doesn't map well to Java
jwharm commented 2025-11-24 23:05:55 +01:00 (Migrated from github.com)

This should call the instance method:

MediaSubSonic s = ...
MediaStream stream = new MediaStream.MediaStream$Impl(s.handle());
stream.seek();

It's a workaround though. I need some more time to properly fix this.

(Edit: Apparently I missed your earlier comment that this workaround indeed works)

This should call the instance method: ```java MediaSubSonic s = ... MediaStream stream = new MediaStream.MediaStream$Impl(s.handle()); stream.seek(); ``` It's a workaround though. I need some more time to properly fix this. (Edit: Apparently I missed your earlier comment that this workaround indeed works)
Nyeksenn commented 2025-11-25 17:42:06 +01:00 (Migrated from github.com)

No problem. Thanks for the suggestion 🙏

No problem. Thanks for the suggestion 🙏
jwharm commented 2025-11-27 21:02:47 +01:00 (Migrated from github.com)

I've created a new cast() method that will help deal with this issue and with #299.

Instead of new MediaStream.MediaStream$Impl(s.handle()).seek() it allows to do:

MediaSubSonic s = ...
s.cast(MediaStream.class).seek();

Or, in case of #299:

StreamVolume sv = pipeline.getByInterface(StreamVolume.getType()).cast(StreamVolume.class);

It's still a workaround, but much cleaner then manually passing a memory address into an Impl class, and the cast() method will perform a runtime check to ensure the instance actually has the requested GType.

The solution is inspired by a similar function in Gtk-rs.

I've created a new `cast()` method that will help deal with this issue and with #299. Instead of `new MediaStream.MediaStream$Impl(s.handle()).seek()` it allows to do: ```java MediaSubSonic s = ... s.cast(MediaStream.class).seek(); ``` Or, in case of #299: ```java StreamVolume sv = pipeline.getByInterface(StreamVolume.getType()).cast(StreamVolume.class); ``` It's still a workaround, but much cleaner then manually passing a memory address into an Impl class, and the `cast()` method will perform a runtime check to ensure the instance actually has the requested GType. The solution is inspired by a similar function in [Gtk-rs](https://gtk-rs.org/gtk-rs-core/git/docs/glib/object/trait.Cast.html).
Nyeksenn commented 2025-11-27 22:19:46 +01:00 (Migrated from github.com)

Thanks. That looks much nicer than instanciating the Impl class.
That's exactly what I was looking for.

Thanks. That looks much nicer than instanciating the Impl class. That's exactly what I was looking for.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
java-gi/java-gi#303
No description provided.