From 5634377fa02e553692b24e097a23ebd0e6c6a927 Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 28 Jan 2021 12:27:16 +0000 Subject: [PATCH] revise binding chapter in docs --- doc/binding.md | 54 +++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/doc/binding.md b/doc/binding.md index a2b2c7a1..851fbdb2 100644 --- a/doc/binding.md +++ b/doc/binding.md @@ -18,12 +18,28 @@ to what you need. # Don't bind the top-level C API -The libvips C API (vips_add() and so on) is very inconvenient and dangerous -to use from other languages due to its heavy use of varargs. +The libvips C API (vips_add() and so on) was designed to be easy for humans +to write. It is inconvenient and dangerous to use from other languages due +to its heavy use of varargs. -It's much better to use the layer below. This lower layer is structured as -create operator, set parameters, execute, extract results. For example, you can -execute vips_invert() like this: +It's much better to use the layer below. This lower layer is structured as: + +- Create operator. You can use vips_operation_new() to make a new + `VipsOperation` object from an operator nickname, like `"add"`. + +- Set parameters. You can loop over the operation with vips_argument_map() to + get the name and type of each input argument. For each argument, you + need to get the value from your language, convert to a `GValue`, then + use g_object_set_property() to set that value on the operator. + +- Execute with vips_cache_operation_build(). + +- Extract results. Again, you loop over the operator arguments with + vips_argument_map(), but instead of inputs, this time you look for output + arguments. You extract their value with g_object_get_property(), and pass + the value back to your language. + +For example, you can execute vips_invert() like this: ```C /* compile with @@ -113,18 +129,11 @@ main( int argc, char **argv ) } ``` -libvips has a couple of extra things to let you examine the arguments and -types of an operator at runtime. Use vips_argument_map() to loop -over all the arguments of an operator, and vips_object_get_argument() -to fetch the type and flags of a specific argument. - -Use vips_operation_get_flags() to get general information about an operator. - # Compiled language which can call C The C++ binding uses this lower layer to define a function called -`VImage::call()` which can call any libvips operator with a not-varargs set of -variable arguments. +`VImage::call()` which can call any libvips operator with a set of variable +arguments. A small Python program walks the set of all libvips operators and generates a set of static bindings. For example: @@ -142,9 +151,9 @@ VImage VImage::invert( VOption *options ) } ``` -So from C++ you can call any libvips operator (though without type-safety) with -`VImage::call()`, or use the member functions on `VImage` to get type-safe -calls for at least the required operator arguments. +So from C++ you can call any libvips operator (though without static +typechecking) with `VImage::call()`, or use the member functions on `VImage` +to get type-checked calls for at least the required operator arguments. The `VImage` class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features. @@ -157,15 +166,14 @@ but use FFI to call into libvips and run operations. Since these languages are dynamic, they can add another trick: they intercept the method-missing hook and attempt to run any method calls not implemented by -the `Image` class as libvips operators. This makes these bindings self-writing: -they only contain a small amount of code and just expose everything they find in -the libvips class hierarchy. +the `Image` class as libvips operators. In effect, the binding is generated at +runtime. # Dynamic langauge without FFI -PHP does not have FFI, unfortunately, so for this language a small native -module implements the general `vips_call()` function for PHP language types, -and a larger pure PHP layer makes it convenient to use. +PHP does not have a useful FFI, unfortunately, so for this language a small +C module implements the general `vips_call()` function for PHP language +types, and a larger pure PHP layer makes it convenient to use. # gobject-introspection