diff --git a/TODO b/TODO index f430cb0f..3614a9dc 100644 --- a/TODO +++ b/TODO @@ -15,7 +15,7 @@ if( !(op = vips_call( "add", in1, in2 )) ) return( -1 ); - g_object_get( G_OBJECT( op ), "out", &x ); + g_object_get( G_OBJECT( op ), "out", &x ); if( im_copy( x, out ) ) { g_object_unref( op ); return( -1 ); @@ -34,12 +34,12 @@ if( !(op = vips_call( "add", in1, in2 )) ) return( -1 ); - g_object_get( G_OBJECT( op ), "out", &out ); + g_object_get( G_OBJECT( op ), "out", &out ); - // do we need to ref out? or unref it? + // do we need to ref out? or unref it? - // then this unref should leave the single ref on out the only thing - // that keeps the add alive, hopefully + // then this unref should leave the single ref on out the + // only thing that keeps the add alive, hopefully g_object_unref( op ); return( out ); @@ -55,6 +55,28 @@ + argh how about on build failure, walk the args and destroy all the values + in case any of them are holding refs to the failed op, then unref the op + + need to check exactly when objects get reffed as they are copied out of + their GValues + + + + + could we support this API still? + + vips_call( "add", in1, in2, &out ) + + walk the valist setting inputs and skipping outputs (they will always be + pointers I guess) + + call build(), bail out on failure destroying unsed outputs as above ^^ + + walk valist again, unboxing and writing to the output pointers + + now unref op, and op will be unreffed when all outputs are destroyed + diff --git a/libvips/arithmetic/arithmetic.c b/libvips/arithmetic/arithmetic.c index 8c64e97b..e501d05b 100644 --- a/libvips/arithmetic/arithmetic.c +++ b/libvips/arithmetic/arithmetic.c @@ -72,19 +72,19 @@ static int vips_arithmetic_build( VipsObject *object ) { VipsArithmetic *arithmetic = VIPS_ARITHMETIC( object ); - VipsImage *out; + VipsImage *out; if( VIPS_OBJECT_CLASS( vips_arithmetic_parent_class )->build( object ) ) return( -1 ); - if( !(out = vips_image_new()) ) + if( !(out = vips_image_new()) ) return( -1 ); - g_object_set( arithmetic, "out", out, NULL ); + g_object_set( arithmetic, "out", out, NULL ); /* Should we _generate() here? We should keep the params in the object * ready to be dropped in. * - * At the moment we _generate() in binary.c and unary.c. + * At the moment we _generate() separately in binary.c and unary.c. */ #ifdef DEBUG diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index eff61483..ff1193e3 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -83,9 +83,7 @@ VIPS_ARGUMENT_REQUIRED_INPUT Eg. the "left" argument for an add operation VIPS_ARGUMENT_OPTIONAL_INPUT Eg. the "caption" for an object -VIPS_ARGUMENT_REQURED_OUTPUT Eg. the "result" of an add operation - -VIPS_ARGUMENT_OPTIONAL_OUTPUT Eg. the "width" of an image +VIPS_ARGUMENT_OUTPUT Eg. the "result" of an add operation Other combinations are used internally, eg. supplying the cast-table for an arithmetic operation @@ -98,19 +96,14 @@ VIPS_ARGUMENT_OPTIONAL_OUTPUT Eg. the "width" of an image VIPS_ARGUMENT_CONSTRUCT | \ VIPS_ARGUMENT_SET_ONCE) -#define VIPS_ARGUMENT_REQUIRED_OUTPUT \ - (VIPS_ARGUMENT_OUTPUT | \ - VIPS_ARGUMENT_REQUIRED | \ - VIPS_ARGUMENT_CONSTRUCT | \ - VIPS_ARGUMENT_SET_ONCE) - #define VIPS_ARGUMENT_OPTIONAL_INPUT \ (VIPS_ARGUMENT_INPUT | \ VIPS_ARGUMENT_CONSTRUCT | \ VIPS_ARGUMENT_SET_ONCE) -#define VIPS_ARGUMENT_OPTIONAL_OUTPUT \ +#define VIPS_ARGUMENT_REQUIRED_OUTPUT \ (VIPS_ARGUMENT_OUTPUT | \ + VIPS_ARGUMENT_REQUIRED | \ VIPS_ARGUMENT_CONSTRUCT | \ VIPS_ARGUMENT_SET_ONCE) diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 52e28d5b..57a5dc44 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -195,8 +195,8 @@ typedef enum { } ArgFlags; static int -vips_operation_set_valist (VipsOperation * operation, - ArgFlags flags, va_list ap) +vips_operation_set_valist (VipsOperation * operation, + ArgFlags flags, va_list ap) { VipsObject *object = VIPS_OBJECT (operation); VipsObjectClass *class = VIPS_OBJECT_GET_CLASS (object); @@ -227,7 +227,8 @@ vips_operation_set_valist (VipsOperation * operation, /* End of stuff copy-pasted from vips_argument_map(). */ - if (argument_class->flags & VIPS_ARGUMENT_REQUIRED && + if ((argument_class->flags & VIPS_ARGUMENT_REQUIRED) && + (argument_class->flags & VIPS_ARGUMENT_INPUT) && !argument_instance->assigned) { GValue value = { 0 };