revise binding chapter in docs

This commit is contained in:
John Cupitt 2021-01-28 12:27:16 +00:00
parent ab06bfb657
commit 5634377fa0
1 changed files with 31 additions and 23 deletions

View File

@ -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