next up previous contents
Next: 4.2 A more complicated Up: 4. Function dispatch and Previous: 4. Function dispatch and   Contents

4.1 Simple plugin example

As an example, consider this function:

#include <stdio.h>

#include <vips/vips.h>
#include <vips/util.h>
#include <vips/dispatch.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 $VIPSHOME/examples/plugin.

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:

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.


Table 4.1: Argument type macros
Macro Meaning im_object has type
IM_INPUT_IMAGEVEC Vector of input images IMAGE **
IM_INPUT_IMAGE Input image IMAGE *
IM_OUTPUT_IMAGE Output image IMAGE *
IM_RW_IMAGE Read-write image IMAGE *
IM_INPUT_DOUBLE Input double double *
IM_INPUT_DOUBLEVEC Input vector of double im_realvec_object *
IM_OUTPUT_DOUBLE Output double double *
IM_INPUT_INT Input int int *
IM_OUTPUT_INT Output int int *
IM_INPUT_STRING Input string char *
IM_OUTPUT_STRING Output string char *
IM_INPUT_DISPLAY Input display im_col_display *
IM_OUTPUT_DISPLAY Output display im_col_display *
IM_OUTPUT_COMPLEX Output complex double *
IM_INPUT_DMASK Input double array im_mask_object *
IM_OUTPUT_DMASK Output double array to file im_mask_object *
IM_OUTPUT_DMASK_STATS Output double array to screen  
IM_INPUT_IMASK Input int array im_mask_object *
IM_OUTPUT_IMASK Output int array to file im_mask_object *


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:

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 */
    NUMBER( arg_types ),  /* # of args */
    arg_types             /* Arg list */
};

NUMBER() is a macro defined in <vips/util.h> 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:

IM_FN_PIO
This function uses the VIPS PIO system (see the Library Programmers' Guide)

IM_FN_TRANSFORM
This the function transforms coordinates.

IM_FN_PTOP
This is a point-to-point operation, that is, it can be replaced with a look-up table.

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 */
    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 do this with:

example% cc -Kpic -I$VIPSHOME/include \
    -c plug.c
example% ld -o double.plg -G plug.o

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%


next up previous contents
Next: 4.2 A more complicated Up: 4. Function dispatch and Previous: 4. Function dispatch and   Contents
John Cupitt 2003-07-21