app, libgimp*, pdb, plug-ins: first step to make int32array PDB type aware of its length.

PDB code is now looking directly into the GimpArray length for
determining the data length.

Also adding a 'size' argument (number of elements, not bytes) to
gimp_value_(get|dup)_int32_array() to make it actually introspectable.
Until now, it was somehow introspected but was segfaulting on run.
I.e. that, e.g. in Python, calling Gimp.value_set_int32_array(v, [1, 2, 3])
followed by Gimp.value_get_int32_array(v) would actually make a
segmentation fault. Now the binding works flawlessly.

This will also make these functions much more usable in general.
This commit is contained in:
Jehan 2024-10-24 09:48:14 +02:00
parent 87d3d921da
commit 60eb27ab18
10 changed files with 59 additions and 19 deletions

View file

@ -1142,7 +1142,7 @@ plug_in_convmatrix_invoker (GimpProcedure *procedure,
divisor = g_value_get_double (gimp_value_array_index (args, 6)); divisor = g_value_get_double (gimp_value_array_index (args, 6));
offset = g_value_get_double (gimp_value_array_index (args, 7)); offset = g_value_get_double (gimp_value_array_index (args, 7));
argc_channels = g_value_get_int (gimp_value_array_index (args, 8)); argc_channels = g_value_get_int (gimp_value_array_index (args, 8));
channels = gimp_value_get_int32_array (gimp_value_array_index (args, 9)); channels = gimp_value_get_int32_array (gimp_value_array_index (args, 9), (gsize *) &argc_channels);
bmode = g_value_get_int (gimp_value_array_index (args, 10)); bmode = g_value_get_int (gimp_value_array_index (args, 10));
if (success) if (success)

View file

@ -192,7 +192,7 @@ gimp_path_get_strokes (GimpPath *path,
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS) if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
{ {
*num_strokes = GIMP_VALUES_GET_INT (return_vals, 1); *num_strokes = GIMP_VALUES_GET_INT (return_vals, 1);
stroke_ids = GIMP_VALUES_DUP_INT32_ARRAY (return_vals, 2); stroke_ids = GIMP_VALUES_DUP_INT32_ARRAY (return_vals, 2, (gsize *) num_strokes);
} }
gimp_value_array_unref (return_vals); gimp_value_array_unref (return_vals);

View file

@ -183,11 +183,11 @@ G_BEGIN_DECLS
/* int32 array */ /* int32 array */
#define GIMP_VALUES_GET_INT32_ARRAY(args, n) \ #define GIMP_VALUES_GET_INT32_ARRAY(args, n, length) \
gimp_value_get_int32_array (gimp_value_array_index (args, n)) gimp_value_get_int32_array (gimp_value_array_index (args, n), length)
#define GIMP_VALUES_DUP_INT32_ARRAY(args, n) \ #define GIMP_VALUES_DUP_INT32_ARRAY(args, n, length) \
gimp_value_dup_int32_array (gimp_value_array_index (args, n)) gimp_value_dup_int32_array (gimp_value_array_index (args, n), length)
#define GIMP_VALUES_SET_INT32_ARRAY(args, n, value, length) \ #define GIMP_VALUES_SET_INT32_ARRAY(args, n, value, length) \
gimp_value_set_int32_array (gimp_value_array_index (args, n), value, length) gimp_value_set_int32_array (gimp_value_array_index (args, n), value, length)

View file

@ -528,32 +528,54 @@ gimp_param_spec_int32_array (const gchar *name,
/** /**
* gimp_value_get_int32_array: * gimp_value_get_int32_array:
* @value: A valid value of type %GIMP_TYPE_INT32_ARRAY * @value: A valid value of type %GIMP_TYPE_INT32_ARRAY
* @length: the number of returned #int32 elements.
* *
* Gets the contents of a %GIMP_TYPE_INT32_ARRAY #GValue * Gets the contents of a %GIMP_TYPE_INT32_ARRAY #GValue
* *
* Returns: (transfer none) (array): The contents of @value * Returns: (transfer none) (array length=length): The contents of @value
*/ */
const gint32 * const gint32 *
gimp_value_get_int32_array (const GValue *value) gimp_value_get_int32_array (const GValue *value,
gsize *length)
{ {
GimpArray *array;
g_return_val_if_fail (GIMP_VALUE_HOLDS_INT32_ARRAY (value), NULL); g_return_val_if_fail (GIMP_VALUE_HOLDS_INT32_ARRAY (value), NULL);
array = value->data[0].v_pointer;
g_return_val_if_fail (array->length % sizeof (gint32) == 0, NULL);
if (length)
*length = array->length / sizeof (gint32);
return (const gint32 *) gimp_value_get_array (value); return (const gint32 *) gimp_value_get_array (value);
} }
/** /**
* gimp_value_dup_int32_array: * gimp_value_dup_int32_array:
* @value: A valid value of type %GIMP_TYPE_INT32_ARRAY * @value: A valid value of type %GIMP_TYPE_INT32_ARRAY
* @length: the number of returned #int32 elements.
* *
* Gets the contents of a %GIMP_TYPE_INT32_ARRAY #GValue * Gets the contents of a %GIMP_TYPE_INT32_ARRAY #GValue
* *
* Returns: (transfer full) (array): The contents of @value * Returns: (transfer full) (array length=length): The contents of @value
*/ */
gint32 * gint32 *
gimp_value_dup_int32_array (const GValue *value) gimp_value_dup_int32_array (const GValue *value,
gsize *length)
{ {
GimpArray *array;
g_return_val_if_fail (GIMP_VALUE_HOLDS_INT32_ARRAY (value), NULL); g_return_val_if_fail (GIMP_VALUE_HOLDS_INT32_ARRAY (value), NULL);
array = value->data[0].v_pointer;
g_return_val_if_fail (array->length % sizeof (gint32) == 0, NULL);
if (length)
*length = array->length / sizeof (gint32);
return (gint32 *) gimp_value_dup_array (value); return (gint32 *) gimp_value_dup_array (value);
} }

View file

@ -239,8 +239,10 @@ GParamSpec * gimp_param_spec_int32_array (const gchar *name,
const gchar *blurb, const gchar *blurb,
GParamFlags flags); GParamFlags flags);
const gint32 * gimp_value_get_int32_array (const GValue *value); const gint32 * gimp_value_get_int32_array (const GValue *value,
gint32 * gimp_value_dup_int32_array (const GValue *value); gsize *length);
gint32 * gimp_value_dup_int32_array (const GValue *value,
gsize *length);
void gimp_value_set_int32_array (GValue *value, void gimp_value_set_int32_array (GValue *value,
const gint32 *data, const gint32 *data,
gsize length); gsize length);

View file

@ -127,6 +127,18 @@ sub marshal_inargs {
$value = "gimp_value_array_index (args, $argc)"; $value = "gimp_value_array_index (args, $argc)";
if (!exists $_->{dead}) { if (!exists $_->{dead}) {
my $var_len;
if (exists $_->{array}) {
my $arrayarg = $_->{array};
if (exists $arrayarg->{name}) {
$var_len = $arrayarg->{name};
}
else {
$var_len = 'num_' . $_->{name};
}
}
$result .= eval qq/" $arg->{get_value_func};\n"/; $result .= eval qq/" $arg->{get_value_func};\n"/;
} }

View file

@ -107,6 +107,7 @@ sub generate_fun {
# Find the return argument (defaults to the first arg if not # Find the return argument (defaults to the first arg if not
# explicitly set # explicitly set
my $retarg = undef; my $retarg = undef;
my $retarg_len = undef;
$retvoid = 0; $retvoid = 0;
foreach (@outargs) { foreach (@outargs) {
$retarg = $_, last if exists $_->{retval}; $retarg = $_, last if exists $_->{retval};
@ -135,7 +136,8 @@ sub generate_fun {
$retarg->{retval} = 1; $retarg->{retval} = 1;
if (exists $argtype->{array}) { if (exists $argtype->{array}) {
$annotate = " (array length=$retarg->{array}->{name})"; $retarg_len = $retarg->{array}->{name};
$annotate = " (array length=$retarg_len)";
} }
if (exists $retarg->{none_ok}) { if (exists $retarg->{none_ok}) {
$annotate .= " (nullable)"; $annotate .= " (nullable)";
@ -367,7 +369,8 @@ CODE
my $var; my $var;
# The return value variable # The return value variable
$var = ""; $var = "";
$var_len = $retarg_len;
unless (exists $_->{retval}) { unless (exists $_->{retval}) {
$var .= '*'; $var .= '*';
@ -386,7 +389,8 @@ CODE
} }
if (exists $arg->{array}) { if (exists $arg->{array}) {
$argdesc .= " (array length=$outargs[$argc - 2]->{name})"; $var_len = $outargs[$argc - 2]->{name};
$argdesc .= " (array length=$var_len)";
} }
if (exists $arg->{out_annotate}) { if (exists $arg->{out_annotate}) {

View file

@ -79,8 +79,8 @@ package Gimp::CodeGen::pdb;
init_value => 'NULL', init_value => 'NULL',
in_annotate => '(element-type gint32)', in_annotate => '(element-type gint32)',
out_annotate => '(element-type gint32) (transfer full)', out_annotate => '(element-type gint32) (transfer full)',
get_value_func => '$var = gimp_value_get_int32_array ($value)', get_value_func => '$var = gimp_value_get_int32_array ($value, (gsize *) &$var_len)',
dup_value_func => '$var = GIMP_VALUES_DUP_INT32_ARRAY ($value)', dup_value_func => '$var = GIMP_VALUES_DUP_INT32_ARRAY ($value, (gsize *) $var_len)',
set_value_func => 'gimp_value_set_int32_array ($value, $var, $var_len)', set_value_func => 'gimp_value_set_int32_array ($value, $var, $var_len)',
take_value_func => 'gimp_value_take_int32_array ($value, $var, $var_len)' }, take_value_func => 'gimp_value_take_int32_array ($value, $var, $var_len)' },

View file

@ -425,7 +425,7 @@ browser_search (GimpBrowser *gimp_browser,
accel_strs = GIMP_VALUES_GET_STRV (return_vals, 2); accel_strs = GIMP_VALUES_GET_STRV (return_vals, 2);
prog_strs = GIMP_VALUES_GET_STRV (return_vals, 3); prog_strs = GIMP_VALUES_GET_STRV (return_vals, 3);
time_ints = GIMP_VALUES_GET_INT32_ARRAY (return_vals, 5); time_ints = GIMP_VALUES_GET_INT32_ARRAY (return_vals, 5, NULL);
for (i = 0; i < num_plugins; i++) for (i = 0; i < num_plugins; i++)
{ {

View file

@ -469,7 +469,7 @@ marshal_returned_PDB_value (scheme *sc,
} }
else if (GIMP_VALUE_HOLDS_INT32_ARRAY (value)) else if (GIMP_VALUE_HOLDS_INT32_ARRAY (value))
{ {
const gint32 *v = gimp_value_get_int32_array (value); const gint32 *v = gimp_value_get_int32_array (value, (gsize *) &array_length);
pointer vector = sc->vptr->mk_vector (sc, array_length); pointer vector = sc->vptr->mk_vector (sc, array_length);
for (j = 0; j < array_length; j++) for (j = 0; j < array_length; j++)