Constructor parameters for JVM-defined GObjects beyond MemorySegment #90

Closed
opened 2024-04-01 05:47:09 +02:00 by sowelipililimute · 3 comments
sowelipililimute commented 2024-04-01 05:47:09 +02:00 (Migrated from github.com)

Currently the only constructor parameter a GObject subclass can have is the MemorySegment required for FFI.

Idiomatic Scala would prefer to have other parameters in the constructor; "null on construction and mutably updated later" to work around this is very unidiomatic in Scala as both null and mutable variables aren't favourably looked upon in most Scala code.

Currently the only constructor parameter a GObject subclass can have is the `MemorySegment` required for FFI. Idiomatic Scala would prefer to have other parameters in the constructor; "null on construction and mutably updated later" to work around this is *very* unidiomatic in Scala as both `null` and mutable variables aren't favourably looked upon in most Scala code.
jwharm commented 2024-04-02 08:30:29 +02:00 (Migrated from github.com)

I'm not sure I understand what you mean. Can you explain what sort of API you'd expect?

Some explanation about the current situation:

Java-GI creates JVM "proxy" instances for all native GObject instances that are used from the JVM side. It will call the MemorySegment constuctor of the JVM class when a native function returns an object for which a JVM proxy doesn't exist yet.

To prevent multiple JVM proxy objects for the same native GObject instance, Java-GI maintains an internal HashMap with all proxy objects. This also allows you to add your own instance fields, pass it to native code, receive it back later, and it's still the same instance. Only when the native GObject instance is disposed, the instance in the Java-GI HashMap is removed.

The MemorySegment constructor is called by Java-GI when a native function returns a GObject instance and a JVM proxy object doesn't exist for it yet. Additional constructor parameters wouldn't make sense there, because the native function only returns a pointer to the existing GObject, so that's all we can pass to a constructor.

However, you can add a second constructor of your own, to create brand new instances of your own classes. That constructor will not have a MemorySegment parameter, because a native GObject doesn't exist yet. So you can do something like this:

public Foo(int bar, String baz) {
    super(gtype, null);
    this.bar = bar;
    this.baz = baz;
}

public static final Type gtype = Types.register(Foo.class);
private final int bar;
private final String baz;

However, this will not work if you have a custom GObject instance initializer method (using an @Init annotation). If you want to do that, you must use a static factory method that calls GObject.newInstance(gtype). That will create the new instance, call its initializer method, and return that instance. A regular super() constructor call cannot do that, which is why I recommend against this in the documentation.

I'm not sure I understand what you mean. Can you explain what sort of API you'd expect? Some explanation about the current situation: Java-GI creates JVM "proxy" instances for all native GObject instances that are used from the JVM side. It will call the `MemorySegment` constuctor of the JVM class when a native function returns an object for which a JVM proxy doesn't exist yet. To prevent multiple JVM proxy objects for the same native GObject instance, Java-GI maintains an internal HashMap with all proxy objects. This also allows you to add your own instance fields, pass it to native code, receive it back later, and it's still the same instance. Only when the native GObject instance is disposed, the instance in the Java-GI HashMap is removed. The `MemorySegment` constructor is called by Java-GI when a native function returns a GObject instance and a JVM proxy object doesn't exist for it yet. Additional constructor parameters wouldn't make sense there, because the native function only returns a pointer to the existing GObject, so that's all we can pass to a constructor. However, you can add a second constructor of your own, to create brand new instances of your own classes. That constructor will not have a `MemorySegment` parameter, because a native GObject doesn't exist yet. So you can do something like this: ``` public Foo(int bar, String baz) { super(gtype, null); this.bar = bar; this.baz = baz; } public static final Type gtype = Types.register(Foo.class); private final int bar; private final String baz; ``` However, this will **not** work if you have a custom GObject instance initializer method (using an `@Init` annotation). If you want to do that, you **must** use a static factory method that calls `GObject.newInstance(gtype)`. That will create the new instance, call its initializer method, and return that instance. A regular `super()` constructor call cannot do that, which is why I recommend against this in the documentation.
jwharm commented 2024-04-18 21:44:33 +02:00 (Migrated from github.com)

@pontaoski Can you please explain a bit more what the expected API would look like?

@pontaoski Can you please explain a bit more what the expected API would look like?
jwharm commented 2024-05-03 22:50:07 +02:00 (Migrated from github.com)

No response, closing

No response, closing
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#90
No description provided.