[gdal-dev] Call for discussion on RFC 59 (v2): GDAL/OGR utilities as a library
Even Rouault
even.rouault at spatialys.com
Tue Sep 1 06:34:32 PDT 2015
Folks,
I'd wish we can find a solution that satisfy all parties. Here's another iteration for a possible proposition.
* C API:
Principles :
- dataset objects can be passed
- the option structure is opaque (should address Frank's concern about exposing too much internal stuff)
- the option structure is parsed from an array of strings (with the current syntax of utilities)
- a few setters can be added, for example, to set a progress function. Or possibly auxiliary objects,
like the cutline layer for gdalwarp.
- not sure if we need the *pbUsageError flag. I removed it. If there's a conflict of options only found after
parsing time (eg due to characteristics of the datasets), then a CPLError() message should be enough.
Example with GDALTranslate:
char** papszArgv = CSLParseCommandLine(const char* pszCommandLine);
GDALTranslateOptionsParse* psOptions = GDALTranslateOptionsNew(char** papszArgv);
GDALTranslateOptionsSetProgress(options, pfnProgress, pProgressData);
hOutDS = GDALTranslate(const char *pszDest, GDALDatasetH hSrcDataset, GDALTranslateOptions *psOptions)
GDALTranslateOptionsDestroy(GDALTranslateOptionsParse* psOptions);
CSLDestroy(papszArgV);
* Python API
Principles :
- use the above C API from SWIG, but mostly for internal use of the upper levels explained below that
would be only Python code (no SWIG).
- pubic API offers access to (hopefully nicely named) dedicated arguments and builds the string from them
- public API offers access to the string representation as well
- use Python dynamic typing to offer sugar candy, e.g pass a SRS either as an osr.SpatialReference()
object or a string (the object being serialized to string, but this is a lossless operation)
Examples:
1) Use case with repeatable options
options = gdal.TranslateOptions()
options.bands = [ 1, 2, 3 ]
options.format = 'MEM'
options.progress = my_progress_method
mem_ds = gdal.Translate('', src_ds, options = options)
2) Variant of 1). With some Python magic on **kwargs it can be automated to redirect on 1)
mem_ds = gdal.Translate('', src_ds, bands = [1,2,3], format = 'MEM', progress = my_progress_method)
3) String oriented.
options = gdal.TranslateOptions('-b 1 -b 2 -b 3 -of MEM')
mem_ds = gdal.Translate('', src_ds, options = options, progress = my_progress_method)
4) Variant of 4)
mem_ds = gdal.Translate('', src_ds, options = '-b 1 -b 2 -b 3 -of MEM', progress = my_progress_method)
5) For the nostalgics, a wrapper of the above :
gdal.Translate('in.tif out.tif -b 1 -b 2 -b 3 -of MEM', progress = my_progress_method')
That's maybe too many different possibilities, although some build upon others, so not necessarily
a lot of code involved (easier to say when it is not coded ahah!)
* Other binding languages.
Would probably only fallback on wrapping C API with SWIG in a first step.
And find most appropriate solutions for each language.
- Java for sure doesn't have a keyword approach for method arguments
(well with what I remember from Java 1.6. might have changed). Builder approach
would be a possibility (http://stackoverflow.com/questions/1988016/named-parameter-idiom-in-java)
- C#: being a clone of Java, probably not.
- Perl: apparently possible
Opinions ?
Even
> Hi Frank,
>
> I was one of the original people who argued against the "array of strings"
> approach...
>
> On 27 August 2015 at 02:26, Frank Warmerdam <warmerdam at pobox.com> wrote:
> > I clearly should have been commenting sooner.
>
> Several months ago :p
>
> > I am concerned that having messy structures of options for each
> > program is going to complicate maintaining the actually commandline
> > programs, and that it will still be a fragile and complicated point of
> > entry as commandline arguments evolve over time.
>
> The commandline tools eventually become string-parsing and wrapping of the
> corresponding library tool - I'm not sure that makes it fragile &
> complicated? Means that the library-ified apps are *at least as*
> flexible/expressive/powerful
> as the command-line tools.
>
> > I'd prefer if the approach had just been to embed the main()'s in a
> > library and to still pass the exact same vector of arguments (in the
> > char **argv format) to these functions instead of shelling out a
> > program.
>
> That kinda defeats the whole point - a huge array of complex string-ified
> arguments is what we're all doing at the moment, wrapped in an subprocess
> call. Some options take multiple arguments in multiple strings, others take
> multiple arguments in single strings, it's massively confusing. And we all
> have big pipelines of chained gdalwarp/gdal_translate/etc code...
>
> What we were striving for was to make it distinctly *better*:
>
> - progress/logging/error handling
> - options that accept geometries or SRS or in-memory datasets without
> having to re-serialize them and/or utilise tempfiles
> - easily applying the same operations over multiple datasets
> - configuration option defaults
>
> > I would love to be able to replace many places where I shell out to
> > run gdal command line programs with a library call with essentially
> > the same arguments.
>
> Sure, so it should be straightforward to do that *as well*, though besides
> in-memory data (as you mention) you're getting very little benefit.
>
> Rob :)
--
Spatialys - Geospatial professional services
http://www.spatialys.com
More information about the gdal-dev
mailing list