As an example, consider this function:
#include <stdio.h> #include <vips/vips.h> /* The function we define. Call this from * other parts of your C application. */ int double_integer( int in ) { return( in * 2 ); }
The source for all the example code in this section is in the vips-examples package.
The first step is to make a layer over this function which will make it look like a standard VIPS function. VIPS insists on the following pattern:
im_error()
.
NULL
-terminated array of im_objects
.
im_object
represents one argument to the function (either output
or input) in the form specified by the corresponding entry in the function's
argument descriptor.
The argument descriptor is an array of structures, each describing one argument. For this example, it is:
/* Describe the type of our function. * One input int, and one output int. */ static im_arg_desc arg_types[] = { IM_INPUT_INT( "in" ), IM_OUTPUT_INT( "out" ) };
IM_INPUT_INT()
and IM_OUTPUT_INT()
are macros defined in
<vips/dispatch.h>
which make argument types easy to define. Other
macros available are listed in table 4.1.
|
The argument to the type macro is the name of the argument. These names are used by user-interface programs to provide feedback, and sometimes as variable names. The order in which you list the arguments is the order in which user-interfaces will present them to the user. You should use the following conventions when selecting names and an order for your arguments:
im_add()
has the following argument names:
example% vips -help im_add vips: args: in1 in2 out where: in1 is of type "image" in2 is of type "image" out is of type "image" add two images, from package "arithmetic" flags: (PIO function) (no coordinate transformation) (point-to-point operation)
im_extract()
has the following sequence of arguments:
example% vips -help im_extract vips: args: input output left top width height channel where: input is of type "image" output is of type "image" left is of type "integer" top is of type "integer" width is of type "integer" height is of type "integer" channel is of type "integer" extract area/band, from package "conversion" flags: (PIO function) (no coordinate transformation) (point-to-point operation)
This function sits over double_integer()
, providing VIPS with an
interface which it can call:
/* Call our function via a VIPS im_object * vector. */ static int double_vec( im_object *argv ) { int *in = (int *) argv[0]; int *out = (int *) argv[1]; *out = double_integer( *in ); /* Always succeed. */ return( 0 ); }
Finally, these two pieces of information (the argument description and the VIPS-style function wrapper) can be gathered together into a function description.
/* Description of double_integer. */ static im_function double_desc = { "double_integer", /* Name */ "double an integer", /* Descrip. */ 0, /* Flags */ double_vec, /* Dispatch */ IM_NUMBER( arg_types ),/* # of args */ arg_types /* Arg list */ };
IM_NUMBER()
is a macro which returns the number of elements in a
static array. The flags
field contains hints which user-interfaces
can use for various optimisations. At present, the possible values are:
This function description now needs to be added to the VIPS function database. VIPS groups sets of related functions together in packages. There is only a single function in this example, so we can just write:
/* Group up all the functions in this * file. */ static im_function *function_list[] = { &double_desc }; /* Define the package_table symbol. This * is what VIPS looks for when loading * the plugin. */ im_package package_table = { "example", /* Package name */ IM_NUMBER( function_list ), function_list /* Function list */ };
The package has to be named package_table
, and has to be exported
from the file (that is, not a static). VIPS looks for a symbol of this name
when it opens your object file.
This file needs to be made into a dynamically loadable object. On my machine, I can do this with:
example% gcc -fPIC -DPIC -c `pkg-config vips-7.10 --cflags` plug.c -o plug.o example% gcc -shared plug.o -o double.plg
You can now use double.plg
with any of the VIPS applications which
support function dispatch. For example:
example% vips -plugin double.plg \ double_integer 12 24 example%
If you copy double.plg
into your VIPS library area (the directory where
libvips is installed) it will be automatically loaded by all VIPS programs as
they start up.