2.99 PDB API enhance: shorter, object-oriented signatures i.e. not pass array length
Summary
This enhancement makes the PDB API signatures shorter, for args that are arrays: eliminates args for length of arrays. Arrays know their own length so you don't need to pass the length.
Similarly, don't return a length arg for arrays. Most callers don't need a length arg, since in a caller's language you can iterate over arrays without the length. If callers need the length, an array has a length method.
The enhancement is PDB API breaking. Now is a good time, for Gimp 3 which breaks the API for other reasons.
The C language libgimp API is unchanged.
The accompanying draft MR demonstrates all aspects. If there is consensus for this enhancement, the MR needs finish and testing.
Examples
This walks through the visible changes to the PDB API, and other things.
Example: gimp-edit-copy, an Internal PDB procedure taking an array
PDB signature
Use the PDB Browser to see this.
Now:
boolean gimp-edit-copy (int, GimpObjectArray)
Enhanced:
boolean gimp-edit-copy (GimpObjectArray)
This is the essential point, the signature is short and natural.
Generated libgimp code
Many methods in libgimp are wrappers around calls to the PDB.
Diff libgimp/gimpedit-pdb.c with master
Here you see that the signature is unchanged, both now and enhanced:
gimp_edit_copy (int, GimpItem **)
That is, libgimp still has a C API, having a separate length arg.
But note that the wrapped call to the PDB is suitably changed:
args = gimp_value_array_new_from_types (NULL,
>>>>>>>>>>>>>> the int length arg is not passed
GIMP_TYPE_OBJECT_ARRAY, NULL,
G_TYPE_NONE);
Generated app code
The generated code in app are "invoker functions", that implement a call to the PDB in terms of calls to core functions.
Diff app/pdb/edit-cmds.c with master
Now:
num_drawables = g_value_get_int (gimp_value_array_index (args, 0));
The length of the array is passed into the invoker function, in an element of the GValueArray passed in a call the a PDB procedure.
Enhanced:
num_drawables = gimp_value_get_array_length (gimp_value_array_index (args, 0))
Here, array length "num_drawables" is gotten from the passed array object, and not directly from a separate element of the GValueArray. The num_drawables is needed to iterate over calls to core.
Example: gimp-get-images, a Internal PDB procedure returning an array.
Similar, use the PDB Browser and see the similar files, just for the function gimp-get-images:
pdb/groups/image.pdb
app/pdb/gimpimage-cmds.c
libgimp/gimpimage-pdb.c
Example: PDB procedures taking/returning array of primitives.
The previous examples were PDB procedures using array of Gimp objects (images, layers, etc.)
The enhancement also works for PDB procedures using arrays of:
primitives (GimpInt32Array and GimpFloatArray)
colors (GimpRGBArray)
An example is the method gimp-plug-ins-query, returning an array of int32.
Note that these arrays of primitives(?) already do not need a separate length arg:
strings (GStrv)
bytes (GBytes)
Example: PDB plugin procedures that are "ImageProcedure"
The enhancement also changes the signature of Plugin PDB procedures of type GimpImageProcedure, aka "filters":
Now:
foo (GimpRunMode, GimpImage, gint, GimpObjectArray, ...)
Enhanced:
foo (GimpRunMode, GimpImage, GimpObjectArray, ...)
In the accompanying draft MR, only the Python/GIR plugin foggify.py is changed. Browse its signature and try Filters>Decor>Fog.
Note that the signature of the "run function" of the plugin is an anomaly:
def foggify(procedure, run_mode, image, n_drawables, drawables, args, data):
It still takes a length arg. This might be a bug in PyGObject, the binding from C to Python. The "run function" is a callback from C.
Changes
This walks through changes to Gimp code to implement the enhancement. See the MR.
To the code generator
Some crux changes are in /pdb i.e. the source for the pdbgen tool. The pdbgen tool generates code for Internal PDB procedures. Diff pdbgen.pl, app.pl, and lib.pl.
There are many more changes in the MR, but they are in generated source. That is, in the generated /app/pdb/foo-cmds.c and /libgimp/gimpfoo-pdb.c files.
The changes to pdbgen are hard to understand because pdbgen is:
- written in Perl
- a non-trivial code generator.
We can document the changes with comments such as:
Don't emit code for a length arg when the next arg is an array.
Use state variables to save an int arg
and optionally emit it after we look at the next arg.
To the PDB language.
The pdb/groups/foo.pdb files are in a small language, say "pdb language." Its a mix of Perl and templates, but it is a language.
The pdb language is unchanged.
Authors of Internal PDB procedures must still declare the length arg associated with an array arg. You still declare the C API:
@inargs = (
{ name => 'drawables', type => 'itemarray',
desc => 'Drawables to copy from',
no_validate => 1,
array => { name => 'num_drawables',
type => '1 <= int32',
desc => "The number of drawables to save" } },
);
To ScriptFu
To ScriptFu scripts calling the PDB
Many will need changes, to eliminate passing length args.
To ScriptFu itself
ScriptFu will need small changes in its argument marshalling code, for arrays of primitives and colors. (only int32_array is implemented in the draft MR.)
To signatures of ScriptFu scripts
Most existing scripts take just one drawable (deprecated.)
Newer scripts, taking multi-layers, will need signatures that omit the array length arg.
Scripts using the v3 script-fu-register-filter method (which automatically declares the Drawables array argument) are exempt from changes to their signature.
To core code for invoking plugins
The code that creates the prefix of args (image, drawables) to a GimpImageProcedure is changed. See /app/actions/procedure-commands.c
The method gimp_value_get_array_length() is added. See /libgimp/gimpparamspec.c.
The Gimp array types are changed so type GimpObjectArray derives from GimpArray, by containing the same fields in the same order, as GLib commonly does. See /libgimp/gimpparamspec.h, the GimpArray struct.
To plugins calling Internal procedure in the PDB
C language callers
No change: C language callers call the libgimp C API which is unchanged.
GIR bound-language callers
Most bound language plugins need no changes, since they use the introspected libgimp C API, which does not change. Note that binding changes the appearance in the bound language of an introspected libgimp call passing an array. That is, a binding should already hide the passing of a length arg. For more discussion, see below "Impact on Python authors"
To plugins calling other plugin procedures in the PDB
This case is the same for C and GIR bound-languages. ScriptFu is not GIR bound.
Plugin PDB procedures are not bound to languages such as Python using GIR. Only Internal PDB procedures are wrapped by libgimp and thus available through introspection.
A C or bound-language plugin calling another plugin in the PDB must chunk an array into a GValue in a GimpValueArray, and then call run_procedure(). Using for example Python:
gvalue = args_gimp_value_array.get_index (2)
Gimp.Value.take_int32_array( gvalue, list )
Gimp.get_pdb().run_procedure ( args_gimp_value_array )
Note that the C signature is:
gimp_value_take_int32_array (GValue, gint32*, gsize)
but since it is annotated for GIR, PyGObject binds the Python "list" argument to the "gint32*, gsize" arguments in a call.
Note that the Python code need NOT put a length argument into the GimpValueArray, because of this enhancement.
See #7369, which is about C language plugins. The code related to #7369 is:
GimpDrawable *drawable_array[2] = ...foo... ; /* a static C array. */
GimpObjectArray *drawables =
gimp_object_array_new (
GIMP_TYPE_DRAWABLE, /* contained type. */
drawable_array, /* C array. */
2, /* length */
TRUE); /* is_static. */
retvals = gimp_pdb_run_procedure (
gimp_get_pdb (),
"proc-name",
GIMP_TYPE_RUN_MODE, GIMP_RUN_NONINTERACTIVE,
GIMP_TYPE_IMAGE, image,
/* No length argument. */
GIMP_TYPE_OBJECT_ARRAY, drawables,
G_TYPE_NONE);
Impact on plugin authors
This discusses the extent of changes to plugins necessitated by this change to the PDB API.
This enhancement has the most impact on plugin signatures, since most take a drawable array. Only a few Internal PDB signatures take or receive arrays.
The draft MR makes a few representative changes to plugin but needs a separate commit to fix the rest of impacted existing plugins.
Impact on ScriptFu script authors
ScriptFu binds to the PDB. Thus this enhancement impacts ScriptFu scripts. Many scripts will need small code deletions, to eliminate length arg in calls to the PDB.
Few ScriptFu scripts take arrays and need changes to their declared signature. Most older scripts take a single Drawable. Newer scripts using standalone interpreter and script-fu-register-filter need not change.
Impact on Python and other bound language authors of plugins
This enhancement does not change the way Python plugins call Gimp. They most often call the libgimp API, which hides a call to the PDB. This enhancement does not change the libgimp API.
But PDB API documents are easier to read for Python script authors. Since the Python binding hides the passing of a container's length to the libgimp API, the signature of a PDB procedure is closer to the signature in Python than the signature documented in the libgimp reference.
For example, the current signature in the API ref:
gboolean
gimp_edit_copy (
gint num_drawables,
const GimpItem** drawables
)
But the Python signature is something like:
Gimp.Edit.copy( list )
In other words, Python authors may prefer the PDB Browser as a reference, versus the libgimp API reference, since the signatures are nearer to what they will use, after this enhancement. They won't have to mentally translate.
Related
This issue is derived from #5919 which is the same but two years old.
This new issue:
-
rewords and fills out the explanation.
-
submits an MR instead of a patch, so you can easily see and test the differences.
-
the issue discusses, and the MR demonstrates, more aspects: receiving arrays, arrays of primitives, changes to plugin signatures, etc. The original patch just demonstrated passing arrays.
This issue is related in goals to !921 (merged) and !389 (merged). There is some discussion in those issues about passing C arrays versus array objects.
Development steps
The draft MR mostly implements this enhancement. After consensus, the MR needs more work, testing, and review.
-
Fix a few more bindings in ScriptFu (float_array and color_array.)
-
Fix plugins that call the changed PDB API:
a. ScriptFu plugins
b. A few C plugins that call other plugins in the PDB (e.g. PluginBrowser)
c. Any bound-language plugins that take or return arrays (other than GimpImageProcedure's Drawables array.)