more cplusplus hackery
This commit is contained in:
parent
904803510d
commit
952241a426
@ -37,10 +37,11 @@
|
||||
#include <cstdio>
|
||||
|
||||
#include <vips/vips.h>
|
||||
#include <vips/internal.h>
|
||||
#include <vips/debug.h>
|
||||
|
||||
#include <vips/vipscpp.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
#include "include/vips/vips8"
|
||||
|
||||
#ifdef WITH_DMALLOC
|
||||
#include <dmalloc.h>
|
||||
@ -54,7 +55,9 @@ VIPS_NAMESPACE_START
|
||||
|
||||
/* Useful to have these as namespaced C++ functions.
|
||||
*/
|
||||
void init( const char *argv0 )
|
||||
void
|
||||
init( const char *argv0 )
|
||||
throw( VError )
|
||||
{
|
||||
if( vips_init( argv0 ) )
|
||||
throw VError();
|
||||
@ -70,14 +73,139 @@ void thread_shutdown()
|
||||
vips_thread_shutdown();
|
||||
}
|
||||
|
||||
static void
|
||||
call_get( GParamSpec *pspec, void *arg )
|
||||
{
|
||||
/* We've read out of the VipsObject to the pointer. If it's a
|
||||
* VipsImage, we need to box it.
|
||||
*/
|
||||
if( G_IS_PARAM_SPEC_OBJECT( pspec ) ) {
|
||||
VImage *image = new VImage( *((VipsImage **) arg) );
|
||||
|
||||
*((VImage *) arg) = *image;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
call_set( GParamSpec *pspec, GValue *value )
|
||||
{
|
||||
if( G_VALUE_HOLDS( value, VIPS_TYPE_IMAGE ) ) {
|
||||
/* A VImage has been written to the GValue, extract the VImage
|
||||
* and swap it for the underlying VipsImage* pointer.
|
||||
*/
|
||||
VImage *image = static_cast<VImage *>(
|
||||
g_value_peek_pointer( value ) );
|
||||
|
||||
g_value_set_object( value, (gpointer) (image->image()) );
|
||||
}
|
||||
}
|
||||
|
||||
/* Some systems do not have va_copy() ... this might work (it does on MSVC,
|
||||
* apparently).
|
||||
*
|
||||
* FIXME ... this should be in configure.in
|
||||
*/
|
||||
#ifndef va_copy
|
||||
#define va_copy(d,s) ((d) = (s))
|
||||
#endif
|
||||
|
||||
void
|
||||
call( const char *operation_name, ... )
|
||||
throw( VError )
|
||||
{
|
||||
VipsCollect collect;
|
||||
VipsOperation *operation;
|
||||
int result;
|
||||
va_list required;
|
||||
va_list optional;
|
||||
|
||||
if( !(operation = vips_operation_new( operation_name )) )
|
||||
throw VError();
|
||||
|
||||
/* We have to break the va_list into separate required and optional
|
||||
* components.
|
||||
*
|
||||
* Note the start, grab the required, then copy and reuse.
|
||||
*/
|
||||
va_start( required, operation_name );
|
||||
|
||||
va_copy( optional, required );
|
||||
|
||||
VIPS_ARGUMENT_FOR_ALL( operation,
|
||||
pspec, argument_class, argument_instance ) {
|
||||
|
||||
g_assert( argument_instance );
|
||||
|
||||
if( (argument_class->flags & VIPS_ARGUMENT_REQUIRED) ) {
|
||||
VIPS_ARGUMENT_COLLECT_SET( pspec, argument_class,
|
||||
optional );
|
||||
|
||||
VIPS_ARGUMENT_COLLECT_GET( pspec, argument_class,
|
||||
optional );
|
||||
|
||||
VIPS_ARGUMENT_COLLECT_END
|
||||
}
|
||||
} VIPS_ARGUMENT_FOR_ALL_END
|
||||
|
||||
collect.get = call_get;
|
||||
collect.set = call_set;
|
||||
result = vips_call_required_optional( &operation,
|
||||
&collect, required, optional );
|
||||
|
||||
va_end( required );
|
||||
va_end( optional );
|
||||
|
||||
/* Build failed: junk args.
|
||||
*/
|
||||
if( result )
|
||||
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
|
||||
|
||||
/* The operation we have built should now have been reffed by one of
|
||||
* its arguments or have finished its work. Either way, we can unref.
|
||||
*/
|
||||
g_object_unref( operation );
|
||||
|
||||
if( result )
|
||||
throw VError();
|
||||
}
|
||||
|
||||
int
|
||||
call_split( const char *operation_name, va_list optional, ... )
|
||||
{
|
||||
VipsOperation *operation;
|
||||
va_list required;
|
||||
VipsCollect collect;
|
||||
int result;
|
||||
|
||||
if( !(operation = vips_operation_new( operation_name )) )
|
||||
throw VError();
|
||||
|
||||
va_start( required, optional );
|
||||
|
||||
collect.get = call_get;
|
||||
collect.set = call_set;
|
||||
result = vips_call_required_optional( &operation,
|
||||
&collect, required, optional );
|
||||
|
||||
va_end( required );
|
||||
|
||||
/* Build failed: junk args.
|
||||
*/
|
||||
if( result )
|
||||
vips_object_unref_outputs( VIPS_OBJECT( operation ) );
|
||||
|
||||
/* The operation we have built should now have been reffed by one of
|
||||
* its arguments or have finished its work. Either way, we can unref.
|
||||
*/
|
||||
g_object_unref( operation );
|
||||
|
||||
if( result )
|
||||
throw VError();
|
||||
}
|
||||
|
||||
// see vips_image_new_from_file()
|
||||
VImage::VImage( const char *name, ... )
|
||||
__attribute__((sentinel)) throw( VError )
|
||||
throw( VError )
|
||||
{
|
||||
char filename[VIPS_PATH_MAX];
|
||||
char option_string[VIPS_PATH_MAX];
|
||||
@ -85,8 +213,6 @@ VImage::VImage( const char *name, ... )
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
vips_check_init();
|
||||
|
||||
vips__filename_split8( name, filename, option_string );
|
||||
if( !(operation_name = vips_foreign_find_load( filename )) )
|
||||
throw VError();
|
||||
@ -102,14 +228,13 @@ VImage::VImage( const char *name, ... )
|
||||
|
||||
// see vips_image_new_from_buffer()
|
||||
VImage::VImage( void *buffer, size_t length, const char *option_string, ... )
|
||||
throw( VError )
|
||||
{
|
||||
const char *operation_name;
|
||||
VipsBlob *blob;
|
||||
va_list ap;
|
||||
int result;
|
||||
|
||||
vips_check_init();
|
||||
|
||||
if( !(operation_name =
|
||||
vips_foreign_find_load_buffer( buffer, length )) )
|
||||
throw VError();
|
||||
@ -130,7 +255,7 @@ VImage::VImage( void *buffer, size_t length, const char *option_string, ... )
|
||||
}
|
||||
|
||||
// see vips_image_write_to_file()
|
||||
void VImage::write( const char *name, ... )
|
||||
void VImage::write_to_file( const char *name, ... )
|
||||
throw( VError )
|
||||
{
|
||||
char filename[VIPS_PATH_MAX];
|
||||
@ -145,7 +270,7 @@ void VImage::write( const char *name, ... )
|
||||
|
||||
va_start( ap, name );
|
||||
result = vips_call_split_option_string( operation_name, option_string,
|
||||
ap, this.im, filename );
|
||||
ap, this->im, filename );
|
||||
va_end( ap );
|
||||
|
||||
if( result )
|
||||
@ -153,7 +278,7 @@ void VImage::write( const char *name, ... )
|
||||
}
|
||||
|
||||
// see vips_image_write_to_buffer()
|
||||
void *VImage::write( const char *suffix, size_t *size, ... )
|
||||
void *VImage::write_to_buffer( const char *suffix, size_t *size, ... )
|
||||
throw( VError )
|
||||
{
|
||||
char filename[VIPS_PATH_MAX];
|
||||
@ -170,7 +295,7 @@ void *VImage::write( const char *suffix, size_t *size, ... )
|
||||
|
||||
va_start( ap, size );
|
||||
result = vips_call_split_option_string( operation_name, option_string,
|
||||
ap, this.im, &blob );
|
||||
ap, this->im, &blob );
|
||||
va_end( ap );
|
||||
|
||||
if( result )
|
||||
@ -194,3 +319,16 @@ void *VImage::write( const char *suffix, size_t *size, ... )
|
||||
#include "vips-operators.cc"
|
||||
|
||||
VIPS_NAMESPACE_END
|
||||
|
||||
|
||||
int
|
||||
main( int argc, char **argv )
|
||||
{
|
||||
vips8::init( argv[0] );
|
||||
|
||||
vips8::VImage x( "/home/john/pics/k2.jpg", NULL );
|
||||
|
||||
printf( "width = %d\n", x.width() );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
@ -79,26 +79,22 @@ public:
|
||||
VImage( const char *filename, const char *mode = "r" )
|
||||
throw( VError )
|
||||
{
|
||||
vips_check_init();
|
||||
|
||||
if( !(im = vips_image_new_mode( filename, mode )) )
|
||||
throw VError();
|
||||
}
|
||||
|
||||
// see vips_image_new_from_file()
|
||||
VImage( const char *name, ... )
|
||||
__attribute__((sentinel)) throw( VError );
|
||||
throw( VError ) __attribute__((sentinel));
|
||||
|
||||
// see vips_image_new_from_buffer()
|
||||
VImage( void *buffer, size_t length, const char *option_string, ... )
|
||||
__attribute__((sentinel)) throw( VError );
|
||||
throw( VError ) __attribute__((sentinel));
|
||||
|
||||
// see vips_image_new_from_memory()
|
||||
VImage( void *data, size_t size, int width, int height,
|
||||
int bands, VipsBandFormat format ) throw( VError )
|
||||
{
|
||||
vips_check_init();
|
||||
|
||||
if( !(im = vips_image_new_from_memory( data, size,
|
||||
width, height, bands, format )) )
|
||||
throw VError();
|
||||
@ -154,15 +150,15 @@ public:
|
||||
throw VError();
|
||||
}
|
||||
|
||||
void write( const char *name, ... )
|
||||
throw( VError );
|
||||
void write_to_file( const char *name, ... )
|
||||
throw( VError )
|
||||
{
|
||||
if( vips_image_write_to_file( im, out.im ) )
|
||||
if( vips_image_write_to_file( im, name, NULL ) )
|
||||
throw VError();
|
||||
}
|
||||
|
||||
// see vips_image_write_to_buffer()
|
||||
void *write( const char *suffix, size_t *size, ... )
|
||||
void *write_to_buffer( const char *suffix, size_t *size, ... )
|
||||
throw( VError );
|
||||
|
||||
// also need
|
||||
|
@ -1,3 +1,3 @@
|
||||
|
||||
VImage add( VImage add_in2, ... )
|
||||
__attribute__((sentinel)) throw( VError );
|
||||
throw( VError ) __attribute__((sentinel));
|
||||
|
@ -37,7 +37,7 @@
|
||||
#define VIPS_NAMESPACE_START namespace vips8 {
|
||||
#define VIPS_NAMESPACE_END }
|
||||
|
||||
#include <vips/VError.h>
|
||||
#include <vips/VImage.h>
|
||||
#include "VError.h"
|
||||
#include "VImage.h"
|
||||
|
||||
#endif /*VIPS_CPLUSPLUS*/
|
||||
|
@ -1,11 +1,11 @@
|
||||
VImage VImage::add( VImage in2 )
|
||||
VImage VImage::add( VImage in2, ... )
|
||||
throw( VError )
|
||||
{
|
||||
va_list ap;
|
||||
VImage out;
|
||||
int result;
|
||||
|
||||
va_start( ap, out );
|
||||
va_start( ap, in2 );
|
||||
result = call_split( "add", ap, this, in2, &out );
|
||||
va_end( ap );
|
||||
|
||||
|
@ -59,6 +59,25 @@ typedef void *(*VipsSListMap4Fn)( void *item,
|
||||
typedef void *(*VipsSListFold2Fn)( void *item,
|
||||
void *a, void *b, void *c );
|
||||
|
||||
/* The value has been read from the VipsOperation and written to the
|
||||
* arg pointer. @arg is eg. gboolean* for a bool value.
|
||||
*/
|
||||
typedef void (*VipsCollectGet)( GParamSpec *pspec, void *arg );
|
||||
|
||||
/* The value has been read from argv into a GValue. Do any
|
||||
* boxing/unboxing before the GValue is used to set the property.
|
||||
*/
|
||||
typedef void (*VipsCollectSet)( GParamSpec *pspec, GValue *value );
|
||||
|
||||
/* We need to be able to use different things to collect values for the C++
|
||||
* API: we have to box and unbox VipsImage. Set/get need to be parameters.
|
||||
*/
|
||||
typedef struct _VipsCollect {
|
||||
VipsCollectGet get;
|
||||
VipsCollectSet set;
|
||||
|
||||
} VipsCollect;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /*__cplusplus*/
|
||||
|
@ -601,7 +601,8 @@ typedef void *(*VipsObjectSetArguments)( VipsObject *object, void *a, void *b );
|
||||
VipsObject *vips_object_new( GType type,
|
||||
VipsObjectSetArguments set, void *a, void *b );
|
||||
|
||||
int vips_object_set_valist( VipsObject *object, va_list ap );
|
||||
int vips_object_set_valist( VipsObject *object,
|
||||
VipsCollect *collect, va_list ap );
|
||||
int vips_object_set( VipsObject *object, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_object_set_from_string( VipsObject *object, const char *string );
|
||||
|
@ -35,8 +35,6 @@
|
||||
extern "C" {
|
||||
#endif /*__cplusplus*/
|
||||
|
||||
#include <vips/vips.h>
|
||||
|
||||
typedef enum /*< flags >*/ {
|
||||
VIPS_OPERATION_NONE = 0,
|
||||
VIPS_OPERATION_SEQUENTIAL = 1,
|
||||
@ -74,20 +72,6 @@ typedef struct _VipsOperation {
|
||||
*/
|
||||
int pixels;
|
||||
|
||||
/* Get and set functions, used by eg. the C++ interface to box and
|
||||
* unbox VImage.
|
||||
*/
|
||||
|
||||
/* The value has been read from the VipsOperation and written to the arg
|
||||
* pointer. @arg is eg. gboolean* for a bool value.
|
||||
*/
|
||||
void (*collect_get)( GParamSpec *pspec, void *arg );
|
||||
|
||||
/* The value has been read from argv into a GValue. Do any
|
||||
* boxing/unboxing before the GValue is used to set the property.
|
||||
*/
|
||||
void (*collect_set)( GParamSpec *pspec, GValue *value );
|
||||
|
||||
} VipsOperation;
|
||||
|
||||
typedef struct _VipsOperationClass {
|
||||
@ -116,6 +100,8 @@ void vips_operation_invalidate( VipsOperation *operation );
|
||||
|
||||
int vips_operation_call_valist( VipsOperation *operation, va_list ap );
|
||||
VipsOperation *vips_operation_new( const char *name );
|
||||
int vips_call_required_optional( VipsOperation **operation,
|
||||
VipsCollect *collect, va_list required, va_list optional );
|
||||
int vips_call( const char *operation_name, ... )
|
||||
__attribute__((sentinel));
|
||||
int vips_call_split( const char *operation_name, va_list optional, ... );
|
||||
|
@ -2155,6 +2155,7 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
|
||||
/**
|
||||
* vips_object_set_valist:
|
||||
* @object: object to set arguments on
|
||||
* @collect: how to box or unbox values
|
||||
* @ap: %NULL-terminated list of argument/value pairs
|
||||
*
|
||||
* See vips_object_set().
|
||||
@ -2162,7 +2163,7 @@ vips_object_new( GType type, VipsObjectSetArguments set, void *a, void *b )
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
int
|
||||
vips_object_set_valist( VipsObject *object, va_list ap )
|
||||
vips_object_set_valist( VipsObject *object, VipsCollect *collect, va_list ap )
|
||||
{
|
||||
char *name;
|
||||
|
||||
@ -2181,6 +2182,9 @@ vips_object_set_valist( VipsObject *object, va_list ap )
|
||||
|
||||
VIPS_ARGUMENT_COLLECT_SET( pspec, argument_class, ap );
|
||||
|
||||
if( collect )
|
||||
collect->set( pspec, &value );
|
||||
|
||||
g_object_set_property( G_OBJECT( object ),
|
||||
name, &value );
|
||||
|
||||
@ -2220,7 +2224,7 @@ vips_object_set( VipsObject *object, ... )
|
||||
int result;
|
||||
|
||||
va_start( ap, object );
|
||||
result = vips_object_set_valist( object, ap );
|
||||
result = vips_object_set_valist( object, NULL, ap );
|
||||
va_end( ap );
|
||||
|
||||
return( result );
|
||||
|
@ -181,6 +181,13 @@
|
||||
* compatibility only and should be hidden from users.
|
||||
*/
|
||||
|
||||
/**
|
||||
* VipsCollect:
|
||||
*
|
||||
* We need to be able to use different things to collect values for the C++
|
||||
* API: we have to box and unbox VipsImage. Set/get need to be parameters.
|
||||
*/
|
||||
|
||||
/* Abstract base class for operations.
|
||||
*/
|
||||
|
||||
@ -567,8 +574,8 @@ vips_operation_new( const char *name )
|
||||
return( operation );
|
||||
}
|
||||
|
||||
/* Some systems do not have va_copy() ... this might work (it does on MSVC),
|
||||
* apparently.
|
||||
/* Some systems do not have va_copy() ... this might work (it does on MSVC,
|
||||
* apparently).
|
||||
*
|
||||
* FIXME ... this should be in configure.in
|
||||
*/
|
||||
@ -577,7 +584,8 @@ vips_operation_new( const char *name )
|
||||
#endif
|
||||
|
||||
static int
|
||||
vips_operation_set_valist_required( VipsOperation *operation, va_list ap )
|
||||
vips_operation_set_valist_required( VipsOperation *operation,
|
||||
VipsCollect *collect, va_list ap )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "vips_operation_set_valist_required:\n" );
|
||||
|
||||
@ -603,8 +611,8 @@ vips_operation_set_valist_required( VipsOperation *operation, va_list ap )
|
||||
}
|
||||
#endif /*VIPS_DEBUG */
|
||||
|
||||
if( operation->collect_set )
|
||||
operation->collect_set( pspec, &value );
|
||||
if( collect )
|
||||
collect->set( pspec, &value );
|
||||
|
||||
g_object_set_property( G_OBJECT( operation ),
|
||||
g_param_spec_get_name( pspec ), &value );
|
||||
@ -624,7 +632,8 @@ vips_operation_set_valist_required( VipsOperation *operation, va_list ap )
|
||||
}
|
||||
|
||||
static int
|
||||
vips_operation_get_valist_required( VipsOperation *operation, va_list ap )
|
||||
vips_operation_get_valist_required( VipsOperation *operation,
|
||||
VipsCollect *collect, va_list ap )
|
||||
{
|
||||
VIPS_DEBUG_MSG( "vips_operation_get_valist_required:\n" );
|
||||
|
||||
@ -672,8 +681,8 @@ vips_operation_get_valist_required( VipsOperation *operation, va_list ap )
|
||||
|
||||
/* Do any boxing/unboxing.
|
||||
*/
|
||||
if( operation->collect_get )
|
||||
operation->collect_get( pspec, arg );
|
||||
if( collect )
|
||||
collect->get( pspec, arg );
|
||||
|
||||
VIPS_ARGUMENT_COLLECT_END
|
||||
}
|
||||
@ -683,7 +692,8 @@ vips_operation_get_valist_required( VipsOperation *operation, va_list ap )
|
||||
}
|
||||
|
||||
static int
|
||||
vips_operation_get_valist_optional( VipsOperation *operation, va_list ap )
|
||||
vips_operation_get_valist_optional( VipsOperation *operation,
|
||||
VipsCollect *collect, va_list ap )
|
||||
{
|
||||
char *name;
|
||||
|
||||
@ -736,8 +746,8 @@ vips_operation_get_valist_optional( VipsOperation *operation, va_list ap )
|
||||
|
||||
/* Do any boxing/unboxing.
|
||||
*/
|
||||
if( operation->collect_get )
|
||||
operation->collect_get( pspec, arg );
|
||||
if( collect )
|
||||
collect->get( pspec, arg );
|
||||
}
|
||||
|
||||
VIPS_ARGUMENT_COLLECT_END
|
||||
@ -746,11 +756,25 @@ vips_operation_get_valist_optional( VipsOperation *operation, va_list ap )
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* This can change operation to point at an old, cached one.
|
||||
/**
|
||||
* vips_call_required_optional:
|
||||
* @operation: the operation to execute
|
||||
* @collect: how to box and unbox arguments
|
||||
* @required: %va_list of required arguments
|
||||
* @optional: NULL-terminated %va_list of name / value pairs
|
||||
*
|
||||
* This is the main entry point for the C and C++ varargs APIs. @operation
|
||||
* is executed, supplying @required and @optional arguments. @collect is used
|
||||
* to do any boxing or unboxing. It can be %NULL for no boxing on unboxing
|
||||
* required (the C case).
|
||||
*
|
||||
* Beware, this can change @operation to point at an old, cached one.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error
|
||||
*/
|
||||
static int
|
||||
int
|
||||
vips_call_required_optional( VipsOperation **operation,
|
||||
va_list required, va_list optional )
|
||||
VipsCollect *collect, va_list required, va_list optional )
|
||||
{
|
||||
int result;
|
||||
va_list a;
|
||||
@ -762,8 +786,8 @@ vips_call_required_optional( VipsOperation **operation,
|
||||
*/
|
||||
va_copy( a, required );
|
||||
va_copy( b, optional );
|
||||
result = vips_operation_set_valist_required( *operation, a ) ||
|
||||
vips_object_set_valist( VIPS_OBJECT( *operation ), b );
|
||||
result = vips_operation_set_valist_required( *operation, collect, a ) ||
|
||||
vips_object_set_valist( VIPS_OBJECT( *operation ), collect, b );
|
||||
va_end( a );
|
||||
va_end( b );
|
||||
|
||||
@ -779,8 +803,10 @@ vips_call_required_optional( VipsOperation **operation,
|
||||
*/
|
||||
va_copy( a, required );
|
||||
va_copy( b, optional );
|
||||
result = vips_operation_get_valist_required( *operation, required ) ||
|
||||
vips_operation_get_valist_optional( *operation, optional );
|
||||
result = vips_operation_get_valist_required( *operation,
|
||||
collect, required ) ||
|
||||
vips_operation_get_valist_optional( *operation,
|
||||
collect, optional );
|
||||
va_end( a );
|
||||
va_end( b );
|
||||
|
||||
@ -801,7 +827,7 @@ vips_call_by_name( const char *operation_name,
|
||||
return( -1 );
|
||||
|
||||
/* Set str options before vargs options, so the user can't override
|
||||
* thnigs we set deliberately.
|
||||
* things we set deliberately.
|
||||
*/
|
||||
if( option_string &&
|
||||
vips_object_set_from_string( VIPS_OBJECT( operation ),
|
||||
@ -812,7 +838,8 @@ vips_call_by_name( const char *operation_name,
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
result = vips_call_required_optional( &operation, required, optional );
|
||||
result = vips_call_required_optional( &operation,
|
||||
NULL, required, optional );
|
||||
|
||||
/* Build failed: junk args and back out.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user