improve configure summary table

- order and group summary
- list by file format type, rather than library
- describe as load/save rather than import/export
- also --vips-config output

I split the VIPS_CFLAGS, VIPS_INCLUDES and VIPS_LIBS var settings into
the various finders for maintainability.
This commit is contained in:
John Cupitt 2021-03-07 12:41:44 +00:00
parent fc4ad15f97
commit fae5d9cc82
2 changed files with 204 additions and 61 deletions

View File

@ -26,7 +26,12 @@ VIPS_MAJOR_VERSION=vips_major_version()
VIPS_MINOR_VERSION=vips_minor_version()
VIPS_MICRO_VERSION=vips_micro_version()
VIPS_VERSION=vips_version()
VIPS_VERSION_STRING=$VIPS_VERSION-`date -u -r $srcdir/ChangeLog`
VIPS_VERSION_STRING="$VIPS_VERSION-$(date -u -r $srcdir/ChangeLog)"
# packages add to these as we find them
VIPS_CFLAGS=""
VIPS_INCLUDES=""
VIPS_LIBS=""
# libtool library versioning ... not user-visible (except as part of the
# library file name) and does not correspond to major/minor/micro above
@ -408,6 +413,9 @@ PKG_CHECK_MODULES(DATE_TIME_FORMAT_ISO8601, glib-2.0 >= 2.62,
]
)
VIPS_CFLAGS="$VIPS_CFLAGS $GIO_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $GIO_LIBS"
# if available, we use pthread_setattr_default_np() to raise the per-thread
# stack size ... musl (libc on Alpine), for example, has a very small stack per
# thread by default
@ -447,6 +455,9 @@ if test x"$expat_found" = x"no"; then
exit 1
fi
VIPS_CFLAGS="$VIPS_CFLAGS $EXPAT_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $EXPAT_LIBS"
# optional supporting libraries
AC_ARG_WITH([gsf],
@ -478,6 +489,9 @@ if test x"$with_gsf" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $GSF_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $GSF_LIBS"
AC_ARG_WITH([fftw],
AS_HELP_STRING([--without-fftw], [build without fftw (default: test)]))
@ -493,6 +507,9 @@ if test x"$with_fftw" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $FFTW_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $FFTW_LIBS"
# ImageMagick
AC_ARG_WITH([magick],
AS_HELP_STRING([--without-magick], [build without libMagic (default: test)]))
@ -652,6 +669,9 @@ else
enable_magicksave=no
fi
VIPS_CFLAGS="$VIPS_CFLAGS $MAGICK_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $MAGICK_LIBS"
# orc
AC_ARG_WITH([orc],
AS_HELP_STRING([--without-orc], [build without orc (default: test)]))
@ -688,6 +708,9 @@ if test x"$with_orc" = x"yes"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $ORC_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $ORC_LIBS"
# lcms ... refuse to use lcms1
AC_ARG_WITH([lcms],
AS_HELP_STRING([--without-lcms], [build without lcms (default: test)]))
@ -708,6 +731,9 @@ fi
# is detected
AM_CONDITIONAL(ENABLE_LCMS, [test x"$with_lcms" != x"no"])
VIPS_CFLAGS="$VIPS_CFLAGS $LCMS_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $LCMS_LIBS"
# OpenEXR
AC_ARG_WITH([OpenEXR],
AS_HELP_STRING([--without-OpenEXR], [build without OpenEXR (default: test)]))
@ -725,6 +751,9 @@ if test x"$with_OpenEXR" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $OPENEXR_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $OPENEXR_LIBS"
# nifti
AC_ARG_WITH([nifti],
AS_HELP_STRING([--without-nifti], [build without nifti (default: test)]))
@ -738,6 +767,10 @@ if test x"$with_nifti" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $NIFTI_CFLAGS"
VIPS_INCLUDES="$VIPS_INCLUDES $NIFTI_INCLUDES"
VIPS_LIBS="$VIPS_LIBS $NIFTI_LIBS"
# libheif
AC_ARG_WITH([heif],
AS_HELP_STRING([--without-heif], [build without libheif (default: test)]))
@ -805,6 +838,9 @@ if test x"$with_heif" = x"yes"; then
CFLAGS="$save_CFLAGS"
fi
VIPS_CFLAGS="$VIPS_CFLAGS $HEIF_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $HEIF_LIBS"
# pdfium
AC_ARG_WITH([pdfium],
AS_HELP_STRING([--without-pdfium], [build without pdfium (default: test)]))
@ -825,6 +861,9 @@ if test x"$with_pdfium" != x"no"; then
])
fi
VIPS_CFLAGS="$VIPS_CFLAGS $PDFIUM_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $PDFIUM_LIBS"
# poppler
AC_ARG_WITH([poppler],
AS_HELP_STRING([--without-poppler], [build without poppler (default: test)]))
@ -840,6 +879,9 @@ if test x"$with_poppler" != x"no"; then
])
fi
VIPS_CFLAGS="$VIPS_CFLAGS $POPPLER_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $POPPLER_LIBS"
# librsvg
AC_ARG_WITH([rsvg],
AS_HELP_STRING([--without-rsvg], [build without rsvg (default: test)]))
@ -856,6 +898,9 @@ if test x"$with_rsvg" != x"no"; then
])
fi
VIPS_CFLAGS="$VIPS_CFLAGS $RSVG_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $RSVG_LIBS"
# zlib
# some platforms, like macosx, are missing the .pc files for zlib, so
# we fall back to FIND_ZLIB
@ -879,6 +924,10 @@ if test x"$with_zlib" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $ZLIB_CFLAGS"
VIPS_INCLUDES="$VIPS_INCLUDES $ZLIB_INCLUDES"
VIPS_LIBS="$VIPS_LIBS $ZLIB_LIBS"
# OpenSlide
AC_ARG_WITH([openslide],
AS_HELP_STRING([--without-openslide],
@ -906,6 +955,9 @@ if test x"$with_openslide" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $OPENSLIDE_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $OPENSLIDE_LIBS"
# matio
AC_ARG_WITH([matio],
AS_HELP_STRING([--without-matio], [build without matio (default: test)]))
@ -922,6 +974,9 @@ if test x"$with_matio" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $MATIO_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $MATIO_LIBS"
# not external libraries, but have options to disable them, helps to
# reduce attack surface
@ -965,6 +1020,9 @@ if test x"$with_cfitsio" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $CFITSIO_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $CFITSIO_LIBS"
# libwebp ... target 0.6+ to reduce complication
# webp has the stuff for handling metadata in two separate libraries -- we
# insit on having all of them
@ -983,6 +1041,9 @@ if test x"$with_libwebp" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $LIBWEBP_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $LIBWEBP_LIBS"
# pangoft2
AC_ARG_WITH([pangoft2],
AS_HELP_STRING([--without-pangoft2],
@ -1000,6 +1061,9 @@ if test x"$with_pangoft2" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $PANGOFT2_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $PANGOFT2_LIBS"
# look for TIFF with pkg-config ... fall back to our tester
# pkgconfig support for libtiff starts with libtiff-4
AC_ARG_WITH([tiff],
@ -1035,6 +1099,10 @@ if test x"$with_tiff" != x"no"; then
INCLUDES="$save_INCLUDES"
fi
VIPS_CFLAGS="$VIPS_CFLAGS $TIFF_CFLAGS"
VIPS_INCLUDES="$VIPS_INCLUDES $TIFF_INCLUDES"
VIPS_LIBS="$VIPS_LIBS $TIFF_LIBS"
# giflib
FIND_GIFLIB(
[with_giflib="yes (found by search)"
@ -1044,6 +1112,10 @@ FIND_GIFLIB(
]
)
VIPS_CFLAGS="$VIPS_CFLAGS $GIFLIB_CFLAGS"
VIPS_INCLUDES="$VIPS_INCLUDES $GIFLIB_INCLUDES"
VIPS_LIBS="$VIPS_LIBS $GIFLIB_LIBS"
# Look for libspng first
# 0.6.1 uses "libspng.pc", git master libspng uses "spng.pc"
AC_ARG_WITH([libspng],
@ -1067,6 +1139,9 @@ if test x"$with_libspng" != x"no"; then
)
fi
VIPS_CFLAGS="$VIPS_CFLAGS $SPNG_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $SPNG_LIBS"
# look for PNG with pkg-config ... fall back to our tester
# we can have both PNG and SPNG enabled, with SPNG for read and PNG for
# write
@ -1102,6 +1177,10 @@ if test x"$with_png" != x"no"; then
CFLAGS="$save_CFLAGS"
fi
VIPS_CFLAGS="$VIPS_CFLAGS $PNG_CFLAGS"
VIPS_INCLUDES="$VIPS_INCLUDES $PNG_INCLUDES"
VIPS_LIBS="$VIPS_LIBS $PNG_LIBS"
# look for libimagequant with pkg-config (only if libpng is enabled)
AC_ARG_WITH([imagequant],
AS_HELP_STRING([--without-imagequant], [build without imagequant (default: test)]))
@ -1120,6 +1199,9 @@ else
with_imagequant=no
fi
VIPS_CFLAGS="$VIPS_CFLAGS $IMAGEQUANT_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $IMAGEQUANT_LIBS"
# look for libjpeg with pkg-config ... fall back to our tester
AC_ARG_WITH([jpeg],
AS_HELP_STRING([--without-jpeg], [build without libjpeg (default: test)]))
@ -1157,6 +1239,10 @@ if test x"$with_jpeg" != x"no"; then
CFLAGS="$save_CFLAGS"
fi
VIPS_CFLAGS="$VIPS_CFLAGS $JPEG_CFLAGS"
VIPS_INCLUDES="$VIPS_INCLUDES $JPEG_INCLUDES"
VIPS_LIBS="$VIPS_LIBS $JPEG_LIBS"
# libexif
AC_ARG_WITH([libexif],
AS_HELP_STRING([--without-libexif], [build without libexif (default: test)]))
@ -1184,6 +1270,9 @@ if test x"$with_libexif" != x"no"; then
CPPFLAGS="$save_CPPFLAGS"
fi
VIPS_CFLAGS="$VIPS_CFLAGS $EXIF_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $EXIF_LIBS"
# fuzzing
AC_ARG_VAR([LIB_FUZZING_ENGINE],
[fuzzing library, e.g. /path/to/libFuzzer.a])
@ -1191,14 +1280,47 @@ if test x"$LIB_FUZZING_ENGINE" = x; then
LIB_FUZZING_ENGINE="libstandaloneengine.a"
fi
# Gather all up for VIPS_CFLAGS, VIPS_INCLUDES, VIPS_LIBS
VIPS_CFLAGS="$VIPS_CFLAGS $GIO_CFLAGS $REQUIRED_CFLAGS $EXPAT_CFLAGS $ZLIB_CFLAGS $PANGOFT2_CFLAGS $GSF_CFLAGS $FFTW_CFLAGS $MAGICK_CFLAGS $JPEG_CFLAGS $SPNG_CFLAGS $PNG_CFLAGS $IMAGEQUANT_CFLAGS $EXIF_CFLAGS $MATIO_CFLAGS $CFITSIO_CFLAGS $LIBWEBP_CFLAGS $GIFLIB_INCLUDES $RSVG_CFLAGS $PDFIUM_CFLAGS $POPPLER_CFLAGS $OPENEXR_CFLAGS $OPENSLIDE_CFLAGS $ORC_CFLAGS $TIFF_CFLAGS $LCMS_CFLAGS $HEIF_CFLAGS" VIPS_CFLAGS="$VIPS_DEBUG_FLAGS $VIPS_CFLAGS"
VIPS_INCLUDES="$ZLIB_INCLUDES $PNG_INCLUDES $TIFF_INCLUDES $JPEG_INCLUDES $NIFTI_INCLUDES"
VIPS_LIBS="$ZLIB_LIBS $HEIF_LIBS $MAGICK_LIBS $SPNG_LIBS $PNG_LIBS $IMAGEQUANT_LIBS $TIFF_LIBS $JPEG_LIBS $GIO_LIBS $REQUIRED_LIBS $EXPAT_LIBS $PANGOFT2_LIBS $GSF_LIBS $FFTW_LIBS $ORC_LIBS $LCMS_LIBS $GIFLIB_LIBS $RSVG_LIBS $NIFTI_LIBS $PDFIUM_LIBS $POPPLER_LIBS $OPENEXR_LIBS $OPENSLIDE_LIBS $CFITSIO_LIBS $LIBWEBP_LIBS $MATIO_LIBS $EXIF_LIBS -lm"
VIPS_CFLAGS="$VIPS_CFLAGS $VIPS_DEBUG_FLAGS $REQUIRED_CFLAGS"
VIPS_LIBS="$VIPS_LIBS $REQUIRED_LIBS -lm"
# autoconf hates multi-line AC_SUBST so we have to have another copy of this
# thing
VIPS_CONFIG="enable debug: $enable_debug, enable deprecated library components: $enable_deprecated, enable docs with gtkdoc: $enable_gtk_doc, gobject introspection: $found_introspection, enable radiance support: $with_radiance, enable analyze support: $with_analyze, enable PPM support: $with_ppm, generate C++ docs: $with_doxygen, use fftw3 for FFT: $with_fftw, Magick package: $with_magickpackage, Magick API version: $magick_version, load with libMagick: $enable_magickload, save with libMagick: $enable_magicksave, accelerate loops with orc: $with_orc, ICC profile support with lcms: $with_lcms, file import with niftiio: $with_nifti, file import with libheif: $with_heif, file import with OpenEXR: $with_OpenEXR, file import with OpenSlide: $with_openslide, file import with matio: $with_matio, PDF import with PDFium: $with_pdfium, PDF import with poppler-glib: $with_poppler, SVG import with librsvg-2.0: $with_rsvg, zlib: $with_zlib, file import with cfitsio: $with_cfitsio, file import/export with libwebp: $with_libwebp, text rendering with pangoft2: $with_pangoft2, file import/export with libspng: $with_libspng, file import/export with libpng: $with_png, support 8bpp PNG quantisation: $with_imagequant, file import/export with libtiff: $with_tiff, file import/export with giflib: $with_giflib, file import/export with libjpeg: $with_jpeg, image pyramid export: $with_gsf, use libexif to load/save JPEG metadata: $with_libexif"
VIPS_CONFIG="\
enable debug: $enable_debug, \
enable deprecated library components: $enable_deprecated, \
enable docs with gtkdoc: $enable_gtk_doc, \
gobject introspection: $found_introspection, \
RAD load/save: $with_radiance, \
Analyze7 load/save: $with_analyze, \
PPM load/save: $with_ppm, \
generate C++ docs: $with_doxygen, \
use fftw3 for FFT: $with_fftw, \
accelerate loops with orc: $with_orc, \
ICC profile support with lcms: $with_lcms, \
zlib: $with_zlib, \
text rendering with pangoft2: $with_pangoft2, \
EXIF metadata support with libexif: $with_libexif, \
JPEG load/save with libjpeg: $with_jpeg, \
PNG load with libspng: $with_libspng, \
PNG load/save with libpng: $with_png, \
8bpp PNG quantisation: $with_imagequant, \
TIFF load/save with libtiff: $with_tiff, \
image pyramid save: $with_gsf, \
GIF load with giflib: $with_giflib, \
HEIC/AVIF load/save with libheif: $with_heif, \
WebP load/save with libwebp: $with_libwebp, \
PDF load with PDFium: $with_pdfium, \
PDF load with poppler-glib: $with_poppler, \
SVG load with librsvg-2.0: $with_rsvg, \
EXR load/save with OpenEXR: $with_OpenEXR, \
slide load with OpenSlide: $with_openslide, \
Matlab load with matio: $with_matio, \
NIfTI load/save with niftiio: $with_nifti, \
FITS load/save with cfitsio: $with_cfitsio, \
Magick package: $with_magickpackage, \
Magick API version: $magick_version, \
load with libMagickCore: $enable_magickload, \
save with libMagickCore: $enable_magicksave"
AC_SUBST(VIPS_LIBDIR)
@ -1261,51 +1383,53 @@ AC_OUTPUT
# also add any new items to VIPS_CONFIG above
AC_MSG_RESULT([dnl
* build options
## Build options
enable debug: $enable_debug
enable deprecated library components: $enable_deprecated
enable docs with gtkdoc: $enable_gtk_doc
gobject introspection: $found_introspection
enable radiance support: $with_radiance
enable analyze support: $with_analyze
enable PPM support: $with_ppm
generate C++ docs: $with_doxygen
gobject introspection: $found_introspection
RAD load/save: $with_radiance
Analyze7 load/save: $with_analyze
PPM load/save: $with_ppm
generate C++ docs: $with_doxygen
* optional dependencies
use fftw3 for FFT: $with_fftw
Magick package: $with_magickpackage
Magick API version: $magick_version
load with libMagick: $enable_magickload
save with libMagick: $enable_magicksave
accelerate loops with orc: $with_orc
(requires orc-0.4.11 or later)
ICC profile support with lcms: $with_lcms
file import with niftiio: $with_nifti
file import with libheif: $with_heif
file import with OpenEXR: $with_OpenEXR
file import with OpenSlide: $with_openslide
(requires openslide-3.3.0 or later)
file import with matio: $with_matio
PDF import with PDFium: $with_pdfium
PDF import with poppler-glib: $with_poppler
(requires poppler-glib 0.16.0 or later)
SVG import with librsvg-2.0: $with_rsvg
(requires librsvg-2.0 2.34.0 or later)
zlib: $with_zlib
file import with cfitsio: $with_cfitsio
file import/export with libwebp: $with_libwebp
(requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later)
text rendering with pangoft2: $with_pangoft2
file import/export with libspng: $with_libspng
(requires libspng-0.6 or later)
file import/export with libpng: $with_png
(requires libpng-1.2.9 or later)
support 8bpp PNG quantisation: $with_imagequant
(requires libimagequant)
file import/export with libtiff: $with_tiff
file import/export with giflib: $with_giflib
file import/export with libjpeg: $with_jpeg
image pyramid export: $with_gsf
(requires libgsf-1 1.14.26 or later)
use libexif to load/save JPEG metadata: $with_libexif
## Optional dependencies
use fftw3 for FFT: $with_fftw
accelerate loops with orc: $with_orc
(requires orc-0.4.11 or later)
ICC profile support with lcms: $with_lcms
zlib: $with_zlib
text rendering with pangoft2: $with_pangoft2
EXIF metadata support with libexif: $with_libexif
## File format support
JPEG load/save with libjpeg: $with_jpeg
PNG load with libspng: $with_libspng
(requires libspng-0.6 or later)
PNG load/save with libpng: $with_png
(requires libpng-1.2.9 or later)
8bpp PNG quantisation: $with_imagequant
(requires libimagequant)
TIFF load/save with libtiff: $with_tiff
image pyramid save: $with_gsf
(requires libgsf-1 1.14.26 or later)
GIF load with giflib: $with_giflib
HEIC/AVIF load/save with libheif: $with_heif
WebP load/save with libwebp: $with_libwebp
(requires libwebp, libwebpmux, libwebpdemux 0.6.0 or later)
PDF load with PDFium: $with_pdfium
PDF load with poppler-glib: $with_poppler
(requires poppler-glib 0.16.0 or later)
SVG load with librsvg-2.0: $with_rsvg
(requires librsvg-2.0 2.34.0 or later)
EXR load/save with OpenEXR: $with_OpenEXR
slide load with OpenSlide: $with_openslide
(requires openslide-3.3.0 or later)
Matlab load with matio: $with_matio
NIfTI load/save with niftiio: $with_nifti
FITS load/save with cfitsio: $with_cfitsio
Magick package: $with_magickpackage
Magick API version: $magick_version
load with libMagickCore: $enable_magickload
save with libMagickCore: $enable_magicksave
])

View File

@ -19,10 +19,35 @@
<refsect3 xml:id="dont-bind-the-top-level-c-api">
<title>Dont bind the top-level C API</title>
<para>
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.
</para>
<para>
Its 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:
Its much better to use the layer below. This lower layer is structured as:
</para>
<itemizedlist>
<listitem>
<para>
Create operator. You can use vips_operation_new() to make a new <literal>VipsOperation</literal> object from an operator nickname, like <literal>&quot;add&quot;</literal>.
</para>
</listitem>
<listitem>
<para>
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 <literal>GValue</literal>, then use g_object_set_property() to set that value on the operator.
</para>
</listitem>
<listitem>
<para>
Execute with vips_cache_operation_build().
</para>
</listitem>
<listitem>
<para>
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.
</para>
</listitem>
</itemizedlist>
<para>
For example, you can execute vips_invert() like this:
</para>
<programlisting language="c">
/* compile with
@ -111,17 +136,11 @@ main( int argc, char **argv )
return( 0 );
}
</programlisting>
<para>
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.
</para>
<para>
Use vips_operation_get_flags() to get general information about an operator.
</para>
</refsect3>
<refsect3 xml:id="compiled-language-which-can-call-c">
<title>Compiled language which can call C</title>
<para>
The C++ binding uses this lower layer to define a function called <literal>VImage::call()</literal> which can call any libvips operator with a not-varargs set of variable arguments.
The C++ binding uses this lower layer to define a function called <literal>VImage::call()</literal> which can call any libvips operator with a set of variable arguments.
</para>
<para>
A small Python program walks the set of all libvips operators and generates a set of static bindings. For example:
@ -139,7 +158,7 @@ VImage VImage::invert( VOption *options )
}
</programlisting>
<para>
So from C++ you can call any libvips operator (though without type-safety) with <literal>VImage::call()</literal>, or use the member functions on <literal>VImage</literal> 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 <literal>VImage::call()</literal>, or use the member functions on <literal>VImage</literal> to get type-checked calls for at least the required operator arguments.
</para>
<para>
The <literal>VImage</literal> class also adds automatic reference counting, constant expansion, operator overloads, and various other useful features.
@ -151,13 +170,13 @@ VImage VImage::invert( VOption *options )
Languages like Ruby, Python, JavaScript and LuaJIT cant call C directly, but they do support FFI. The bindings for these languages work rather like C++, but use FFI to call into libvips and run operations.
</para>
<para>
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 <literal>Image</literal> 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.
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 <literal>Image</literal> class as libvips operators. In effect, the binding is generated at runtime.
</para>
</refsect3>
<refsect3 xml:id="dynamic-langauge-without-ffi">
<title>Dynamic langauge without FFI</title>
<para>
PHP does not have FFI, unfortunately, so for this language a small native module implements the general <literal>vips_call()</literal> 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 <literal>vips_call()</literal> function for PHP language types, and a larger pure PHP layer makes it convenient to use.
</para>
</refsect3>
<refsect3 xml:id="gobject-introspection">