From f7f061d265621fd1443120dfdd33ba3c7274f19d Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Sun, 20 Oct 2013 16:46:55 +0100 Subject: [PATCH] vips_init() does ABI checking just checks sizeof(VipsObject) for now --- ChangeLog | 4 +++- TODO | 12 ------------ libvips/deprecated/vips7compat.c | 6 ++++++ libvips/include/vips/private.h | 5 +++++ libvips/include/vips/vips.h | 14 +++++++++++++- libvips/include/vips/vips7compat.h | 3 ++- libvips/iofuncs/init.c | 23 +++++++++++++++++++++-- 7 files changed, 50 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1aba8933..5c7cc703 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 19/10/13 started 7.37.0 -- redone im_rotate_*mask45(), im_gauss_*mask*(), im_log_*mask*() as classes +- redone im_rotate_*mask45(), im_gauss_*mask*(), im_log_*mask() as classes +- vips_init() now does some ABI compat checking, though this change requires + an ABI break 18/10/13 started 7.36.3 - fix compiler warnings in ubuntu 13.10 diff --git a/TODO b/TODO index ff93a325..b4aed4ea 100644 --- a/TODO +++ b/TODO @@ -1,15 +1,3 @@ -- do log mask generation, common base class with the gauss mask builder? - -- make vips_init() into a macro, check sizes of important structs against size - at library compile time - - add a new API call like vips__get_sizeof_image() which returns - sizeof(VipsImage) from library compile time, compare that to the application - compile-time value - - vips_init() macro then passes control on to vips__init() for real startup - - breaks binary API sadly - do conv and morph quickly as simple wrappers over the vips7 operations diff --git a/libvips/deprecated/vips7compat.c b/libvips/deprecated/vips7compat.c index 3f46f2a6..3c31ff14 100644 --- a/libvips/deprecated/vips7compat.c +++ b/libvips/deprecated/vips7compat.c @@ -50,6 +50,12 @@ #include #include +int +im_init_world( const char *argv0 ) +{ + return( vips_init( argv0 ) ); +} + VipsImage * im_open( const char *filename, const char *mode ) { diff --git a/libvips/include/vips/private.h b/libvips/include/vips/private.h index 03479055..123dda67 100644 --- a/libvips/include/vips/private.h +++ b/libvips/include/vips/private.h @@ -56,6 +56,11 @@ extern "C" { */ #define VIPS_SIZEOF_HEADER (64) +/* Startup plus ABI check. + */ +int vips__init( const char *argv0 ); +size_t vips__get_sizeof_vipsobject( void ); + /* What we track for each mmap window. Have a list of these on an openin * VipsImage. */ diff --git a/libvips/include/vips/vips.h b/libvips/include/vips/vips.h index 85078776..ca777e0f 100644 --- a/libvips/include/vips/vips.h +++ b/libvips/include/vips/vips.h @@ -149,8 +149,20 @@ extern "C" { #include #include +#define vips_init( ARGV0 ) \ + (sizeof( VipsObject ) != vips__get_sizeof_vipsobject() ? ( \ + vips_info( "vips_init", "%s", _( "ABI mismatch" ) ), \ + vips_info( "vips_init", \ + _( "library has sizeof(VipsObject) == %zd" ), \ + vips__get_sizeof_vipsobject() ), \ + vips_info( "vips_init", \ + _( "application has sizeof(VipsObject) == %zd" ), \ + sizeof( VipsObject() ) ), \ + vips_error( "vips_init", "%s", _( "ABI mismatch" ) ), \ + -1 ) : \ + vips__init( ARGV0 )) + const char *vips_get_argv0( void ); -int vips_init( const char *argv0 ); void vips_check_init( void ); void vips_shutdown( void ); GOptionGroup *vips_get_option_group( void ); diff --git a/libvips/include/vips/vips7compat.h b/libvips/include/vips/vips7compat.h index 32c3d88d..04a0e151 100644 --- a/libvips/include/vips/vips7compat.h +++ b/libvips/include/vips/vips7compat.h @@ -203,7 +203,6 @@ extern "C" { #define im_get_argv0 vips_get_argv0 #define im_version_string vips_version_string #define im_version vips_version -#define im_init_world vips_init #define im_get_option_group vips_get_option_group #define im_guess_prefix vips_guess_prefix #define im_guess_libdir vips_guess_libdir @@ -586,6 +585,8 @@ size_t im_ref_string_get_length( const GValue *value ); #define im_concurrency_set vips_concurrency_set #define im_concurrency_get vips_concurrency_get +int im_init_world( const char *argv0 ); + int im_add( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_subtract( VipsImage *in1, VipsImage *in2, VipsImage *out ); int im_multiply( VipsImage *in1, VipsImage *in2, VipsImage *out ); diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index eac7745e..74390550 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -140,7 +140,7 @@ vips_get_argv0( void ) * * * - * loads any plugins from $libdir/vips-x.y, where x and y are the + * loads any plugins from $libdir/vips-x.y/, where x and y are the * major and minor version numbers for this VIPS. * * @@ -165,8 +165,13 @@ vips_get_argv0( void ) * * Returns: 0 on success, -1 otherwise */ + +/* vips_init() is actually a macro which checks library and application + * compatibility before calling vips__init(). + */ + int -vips_init( const char *argv0 ) +vips__init( const char *argv0 ) { extern GType vips_system_get_type( void ); @@ -299,6 +304,20 @@ vips_init( const char *argv0 ) return( 0 ); } +/* Return the sizeof() various important data structures. These are checked + * against the headers used to build our caller by vips_init(). + * + * We allow direct access to members of VipsImage and VipsRegion (mostly for + * reasons of history), so any change to a superclass of either of these + * objects will break our ABI. + */ + +size_t +vips__get_sizeof_vipsobject( void ) +{ + return( sizeof( VipsObject ) ); +} + /* Call this before vips stuff that uses stuff we need to have inited. */ void