Skip to content

Commit

Permalink
Merge pull request #163 from jwharm/127-register-interfaces-and-enums
Browse files Browse the repository at this point in the history
Merge branch 127-register-interfaces-and-enums
  • Loading branch information
jwharm authored Dec 12, 2024
2 parents 8f3b268 + 7ba8e35 commit dac08b2
Show file tree
Hide file tree
Showing 16 changed files with 902 additions and 344 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ else if (((target instanceof Record record
// No ownership transfer: Copy/ref the struct
else {
// First check for NULL
if (returnValue.nullable()) {
if (generator.checkNull()) {
builder.beginControlFlow("if (_result == null || _result.equals($T.NULL))",
MemorySegment.class)
.addStatement("return null")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@
import io.github.jwharm.javagi.gir.Record;
import io.github.jwharm.javagi.util.Patch;

import java.util.Collections;
import java.util.List;
import java.util.Map;

import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;

public class GObjectPatch implements Patch {

@Override
Expand Down Expand Up @@ -55,7 +57,7 @@ public GirElement patch(GirElement element, String namespace) {
&& "TYPE_FLAG_RESERVED_ID_BIT".equals(c.name())) {
Type type = new Type(
Map.of("name", "gsize", "c:type", "gsize"),
Collections.emptyList()
emptyList()
);
return c.withChildren(
c.infoElements().doc(),
Expand All @@ -72,7 +74,7 @@ public GirElement patch(GirElement element, String namespace) {
if (element instanceof Alias a && "Type".equals(a.name())) {
Type type = new Type(
Map.of("name", "GLib.Type", "c:type", "gtype"),
Collections.emptyList()
emptyList()
);
return a.withChildren(a.infoElements().doc(), type);
}
Expand Down Expand Up @@ -105,7 +107,7 @@ public GirElement patch(GirElement element, String namespace) {
Type type = new Type(
Map.of("name", "GObject.ObjectClass",
"c:type", "GObjectClass"),
Collections.emptyList()
emptyList()
);
Field field = new Field(
Map.of("name", "parent_class"),
Expand Down Expand Up @@ -144,6 +146,20 @@ public GirElement patch(GirElement element, String namespace) {
vm.platforms()
);

/*
* Workaround for https://gitlab.gnome.org/GNOME/glib/-/issues/3524
*/
if (element instanceof Type t
&& (("EnumValue".equals(t.name())
&& "const GEnumValue*".equals(t.cType()))
|| ("FlagsValue".equals(t.name())
&& "const GFlagsValue*".equals(t.cType())))) {
var name = t.name();
var cType = "const G" + name;
return new Array(emptyMap(), List.of(
new Type(Map.of("name", name, "c:type", cType), emptyList())));
}

return element;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1313,12 +1313,13 @@ public static MemorySegment allocateNativeArray(Proxy[] array,

/**
* Allocate and initialize an (optionally {@code NULL}-terminated) array of
* structs (from Proxy instances). The actual memory segments (not the
* structs (from Proxy instances). The actual struct contents (not the
* pointers) are copied into the array.
*
* @param array array of Proxy instances
* @param layout the memory layout of the object type
* @param zeroTerminated whether to add a {@code NULL} to the array
* @param layout the memory layout of the struct
* @param zeroTerminated whether to terminate the array by a struct with
* all members being {@code NULL}
* @param arena the allocator for memory allocation
* @return the memory segment of the native array
*/
Expand All @@ -1344,7 +1345,8 @@ public static MemorySegment allocateNativeArray(Proxy[] array,
}

if (zeroTerminated)
segment.set(ValueLayout.ADDRESS, length * size, NULL);
// The array is zero-terminated by a struct with all members being 0
segment.asSlice(array.length * size, size).fill((byte) 0);

return segment;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ default Ref asStrong() {
* @param address get the Proxy object for this address from the cache
* @return the instance (if found), or null (if not found)
*/
private static Proxy get(MemorySegment address) {
private static Proxy lookup(MemorySegment address) {

// Null check on the memory address
if (address == null || address.equals(MemorySegment.NULL))
Expand Down Expand Up @@ -158,11 +158,11 @@ public static Proxy getForType(MemorySegment address,
boolean cache) {

// Get instance from the cache
Proxy instance = get(address);
Proxy instance = lookup(address);
if (instance != null)
return instance;

// Get constructor from the type registry
// Read gclass->gtype and get constructor from the type registry
Function<MemorySegment, ? extends Proxy> ctor =
TypeCache.getConstructor(address, fallback);
if (ctor == null)
Expand Down Expand Up @@ -219,8 +219,7 @@ public static Proxy getForTypeClass(MemorySegment address,
return fallback.apply(address);

// Get the Java proxy TypeClass definition
TypeInstance typeInstance = (TypeInstance) newInstance;
Class<? extends TypeInstance> instanceClass = typeInstance.getClass();
Class<? extends Proxy> instanceClass = newInstance.getClass();
Class<? extends TypeClass> typeClass = Types.getTypeClass(instanceClass);
if (typeClass == null)
return fallback.apply(address);
Expand Down Expand Up @@ -254,7 +253,7 @@ public static Proxy get(MemorySegment address,
boolean cache) {

// Get instance from the cache
Proxy instance = get(address);
Proxy instance = lookup(address);
if (instance != null)
return instance;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* Java-GI - Java language bindings for GObject-Introspection-based libraries
* Copyright (C) 2022-2024 Jan-Willem Harmannij
*
* SPDX-License-Identifier: LGPL-2.1-or-later
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

package io.github.jwharm.javagi.gobject.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import io.github.jwharm.javagi.gobject.types.Types;

/**
* The {@code @Flags} annotation is used by {@link Types#register} to register
* a Java enum as a GObject Flags type. Flags types are like enumerations, but
* allow bitwise comparison of their values.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Flags {
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@
@Target(ElementType.TYPE)
public @interface RegisteredType {
String name() default "";
Class<?>[] prerequisites() default {};
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@
import org.gnome.glib.GLib;
import org.gnome.glib.LogLevelFlags;
import org.gnome.glib.Type;
import org.gnome.gobject.GObject;
import org.gnome.gobject.GObjects;
import org.gnome.gobject.TypeInterface;
import org.gnome.gobject.*;

import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
Expand Down Expand Up @@ -92,14 +90,10 @@ private static String getOverrideName(Method method) {
* method overrides in the class virtual function table.
*
* @param cls the class that possibly declares method overrides
* @param <T> the class must extend {@link GObject}
* @param <TC> the returned lambda expects a {@link GObject.ObjectClass}
* parameter
* @return a lambda to run during class initialization that will register
* the virtual functions
*/
public static <T extends GObject, TC extends GObject.ObjectClass>
Consumer<TC> overrideClassMethods(Class<T> cls) {
public static Consumer<TypeClass> overrideClassMethods(Class<?> cls) {

Class<?> typeStruct = Types.getTypeClass(cls);
if (typeStruct == null)
Expand Down Expand Up @@ -192,13 +186,13 @@ private static Method findMethod(Class<?> cls,
*
* @param cls the class that possibly declares method overrides
* @param iface the interface from which methods are implemented
* @param <T> the class must extend {@link GObject}
* @param <T> the class must extend {@link TypeInstance}
* @param <TI> the returned lambda expects a {@link TypeInterface}
* parameter
* @return a lambda to run during interface initialization that will
* register the virtual functions
*/
static <T extends GObject, TI extends TypeInterface>
static <T extends TypeInstance, TI extends TypeInterface>
Consumer<TI> overrideInterfaceMethods(Class<T> cls, Class<?> iface) {

// Lookup the memory address constructor for the TypeInterface
Expand Down
Loading

0 comments on commit dac08b2

Please sign in to comment.