[Gdal-dev] Re: gdal swig interface Band.i Updated

Charlie Savage cfis at savagexi.com
Fri Aug 4 18:41:53 EDT 2006


The proposed wrapper code is correct.

%apply (int *OUTPUT){int *blockXSize, int *blockYSize}
   void GetBlockSize(int *blockXSize, int *blockYSize){
               GDALGetBlockSize(self, blockXSize, blockYSize);
   }


And could be further simplified to:

   void GetBlockSize(int *OUTPUT, int *OUTPUT){
               GDALGetBlockSize(self, blockXSize, blockYSize);
   }

What's nice is that it will work with all SWIG languages.  For those 
interested, some more technical background below.


Charlie

------------

Three are three ways to wrap output parameters in SWIG.  To show them, 
let's walk through an example:

void add(int x, int y, int *result)
{
   *result = x + y;
}

1.  Using OUTPUT, so:

void add(int, int, int *OUTPUT);

2.  Use %apply, like this:

%apply int *OUTPUT { int *result };
void add(int x, int y, int *result);

#1 is shorthand for #2.  Both have SWIG generate the wrapper code for you.

3.  Create the wrapper code yourself by using typemaps.


> I don't see anything obviously wrong with your formulation, but when
> I look in Band.i or the various other .i files I don't see anything
> quite analygous to your approach either.  Some other functions that
> return values in variables to which passed pointers are provided just
> look like this:
> 
>   void GetOffset( double *val, int *hasval ) {
>     *val = GDALGetRasterOffset( self, hasval );
>   }
> 
> I'm not sure if "val and hasval" are special names or exactly what
> makes this work.  But it makes me wonder if the approach you suggest
> is appropriate.

GetOffset is an example of option #3 above.  You can find the right type 
map for this method in each language file. Using Python as an example, 
look at line 212 in typemaps_python.i.


Part 1:

%typemap(python,in,numinputs=0) (double *val, int*hasval) ( double 
tmpval, int tmphasval ) {
   $1 = &tmpval;
   $2 = &tmphasval;
}

Before GDalGetRasterOffset is called, define two local variable. 
Pointers to these local variable will be the parameters used in the 
GDalGetRasterOffset call.


Part 2:

%typemap(python,argout) (double *val, int*hasval) {
   PyObject *r;
   if ( !*$2 ) {
     Py_INCREF(Py_None);
     r = Py_None;
     $result = t_output_helper($result,r);
   }
   else {
     r = PyFloat_FromDouble( *$1 );
     $result = t_output_helper($result,r);
   }
}

After GDalGetRasterOffset is called, check to see if hasVal is true or 
false.  If false, return Py_None (null in python).  If true, wrap val as 
a Python double object.

The reason this typemap exists is because of the extra logic involved 
needed to figure out what to do with the result.


Fake Classes
--------------

Also, a bit of backround about how the SWIG bindings are structured. 
They create "fake" classes so from Python or Ruby or Java or whatever, 
there is a class called GDALRasterBand which has a method called GetOffset.

Using these "fake" classes is a very unusual approach.  Usually, SWIG is 
used to directly wrap C++ classes so there is no need for the "fake" 
classes.

However, the GDAL bindings use the c api not the c++ api.  But if you 
exposed the C api to python or ruby, it would create an API very foreign 
to the average Python/Ruby programmer.  Thus the "fake" classes make the 
  c api look object oriented.

The advantage of this approach is you can tightly control the exposed 
api.  I think the other thought was that client programs linking against 
the C api would be more stable.  This is true for c or c++ clients, but 
I don't think is true for Python/Ruby clients.  This is because they 
provide APIs through which you register new methods - its not like a C++ 
program where the links are setup as pointers.  So when you provide a 
new gdal c lib, and the associated language binding libraries, a python 
or ruby program is not going to care that it has changed.

The disadvantage is that its a lot of extra work and complexity, and 
you're not going to find examples of how to do it out on the Web.

Anyway, hope this helps.





More information about the Gdal-dev mailing list