From 093f042cc5e6ddfc6909ae0d2cb2d603a529c5ea Mon Sep 17 00:00:00 2001 From: Angelo Verlain Date: Tue, 26 Dec 2023 21:19:51 +0200 Subject: [PATCH] allow setting vfuncs provided by interfaces --- src/bindings/girepository.js | 1 + src/types/callable.js | 39 +++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/bindings/girepository.js b/src/bindings/girepository.js index 0b1cc06..a15132c 100644 --- a/src/bindings/girepository.js +++ b/src/bindings/girepository.js @@ -101,6 +101,7 @@ const { g } = openLib(libName("girepository-1.0", 1), { get_vfunc: $pointer($pointer, $i32), get_n_properties: $i32($pointer), get_property: $pointer($pointer, $i32), + get_iface_struct: $pointer($pointer), }, property_info: { get_flags: $i32($pointer), diff --git a/src/types/callable.js b/src/types/callable.js index 8d00a8f..84bb20e 100644 --- a/src/types/callable.js +++ b/src/types/callable.js @@ -137,24 +137,43 @@ export function handleCallable(target, info) { set(value) { const cName = g.base_info.get_name(info); - const objectInfo = g.base_info.get_container(info); - const classStruct = g.object_info.get_class_struct(objectInfo); - const fieldInfo = g.struct_info.find_field(classStruct, cName); + const containerInfo = g.base_info.get_container(info); + const containerType = g.base_info.get_type(containerInfo); + + let containerStruct, pointer; + + if (containerType === GIInfoType.INTERFACE) { + // we are setting a vfunc provided by an interface + containerStruct = g.interface_info.get_iface_struct(containerInfo); + const klass = g.type_class.ref( + Reflect.getOwnMetadata("gi:gtype", this.constructor), + ); + // get the pointer to the interface struct of this class + pointer = g.type_interface.peek( + klass, + g.registered_type_info.get_g_type(containerInfo), + ); + } else { + // we are directly setting a vfunc provided by a class + containerStruct = g.object_info.get_class_struct(containerInfo); + pointer = g.type_class.ref( + Reflect.getOwnMetadata("gi:gtype", this.constructor), + ); + } + + const fieldInfo = g.struct_info.find_field(containerStruct, cName); if (!fieldInfo) { - // This vfunc doesn't have a corresponding field in the class struct + // This vfunc doesn't have a corresponding field in the class or + // interface struct return; } - const klass = g.type_class.ref( - Reflect.getOwnMetadata("gi:gtype", this.constructor), - ); - - const cb = createCallback(info, value); + const cb = createCallback(info, value, this); const offset = g.field_info.get_offset(fieldInfo); const dataView = new ExtendedDataView( deref_buf( - klass, + pointer, offset + 8, offset, ),