diff --git a/TODO b/TODO index f1370662..a95bdc25 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,3 @@ -- oops - - $ vips avg - Segmentation fault - - because we don't test that all args have been set until the end of build, - and statistic_build assumes that in has been set - - - is our C API too awkward? we'll need diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index d0605b63..027e67f0 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -132,6 +132,7 @@ vips_object_check_required( VipsObject *object, GParamSpec *pspec, void *a, void *b ) { int *result = (int *) a; + VipsArgumentFlags *iomask = (VipsArgumentFlags *) b; VIPS_DEBUG_MSG( "vips_object_check_required: %s\n", g_param_spec_get_name( pspec ) ); @@ -139,11 +140,16 @@ vips_object_check_required( VipsObject *object, GParamSpec *pspec, argument_class->flags & VIPS_ARGUMENT_REQUIRED ); VIPS_DEBUG_MSG( "\tconstruct: %d\n", argument_class->flags & VIPS_ARGUMENT_CONSTRUCT ); + VIPS_DEBUG_MSG( "\tinput: %d\n", + argument_class->flags & VIPS_ARGUMENT_INPUT ); + VIPS_DEBUG_MSG( "\toutput: %d\n", + argument_class->flags & VIPS_ARGUMENT_OUTPUT ); VIPS_DEBUG_MSG( "\tassigned: %d\n", argument_instance->assigned ); if( (argument_class->flags & VIPS_ARGUMENT_REQUIRED) && (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT) && + (argument_class->flags & *iomask) && !argument_instance->assigned ) { vips_error( "VipsObject", /* used as eg. "parameter out to VipsAdd not set". @@ -162,6 +168,11 @@ vips_object_build( VipsObject *object ) { VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object ); + /* Input and output args must both be set. + */ + VipsArgumentFlags iomask = + VIPS_ARGUMENT_INPUT | VIPS_ARGUMENT_OUTPUT; + int result; #ifdef DEBUG @@ -178,7 +189,7 @@ vips_object_build( VipsObject *object ) */ result = 0; (void) vips_argument_map( object, - vips_object_check_required, &result, NULL ); + vips_object_check_required, &result, &iomask ); /* ... more checks go here. */ @@ -893,6 +904,13 @@ vips_object_real_build( VipsObject *object ) { VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( object ); + /* Only test input args, output ones can be set by our subclasses as + * they build. See vips_object_build() above. + */ + VipsArgumentFlags iomask = VIPS_ARGUMENT_INPUT; + + int result; + #ifdef DEBUG printf( "vips_object_real_build: " ); vips_object_print_name( object ); @@ -909,14 +927,14 @@ vips_object_real_build( VipsObject *object ) "nickname", object_class->nickname, "description", object_class->description, NULL ); - /* We can't check that all required args have been set here, since our - * superclasses' build funcs might want to set some one the way out, - * see VipsAvg, for example. - * - * Do these checks in the build dispatch function, see above. + /* Check all required input arguments have been supplied, don't stop + * on 1st error. */ + result = 0; + (void) vips_argument_map( object, + vips_object_check_required, &result, &iomask ); - return( 0 ); + return( result ); } static void diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index cf96d009..9d21ffe5 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -28,8 +28,8 @@ */ /* - */ #define VIPS_DEBUG + */ #ifdef HAVE_CONFIG_H #include