Geo-GDAL-FFI-0.16/ 0000755 0001755 0001755 00000000000 15201444007 012304 5 ustar pause pause Geo-GDAL-FFI-0.16/t/ 0000755 0001755 0001755 00000000000 15201443773 012560 5 ustar pause pause Geo-GDAL-FFI-0.16/t/vsistdout.t 0000644 0001755 0001755 00000005337 15201245115 015007 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Encode qw(decode encode);
use Geo::GDAL::FFI qw/GetDriver/;
use Test::More;
use Data::Dumper;
use JSON;
my $mem_driver = Geo::GDAL::FFI::get_memory_driver;
{
package Output;
use strict;
use warnings;
our @output;
sub new {
return bless {}, 'Output';
}
sub write {
my $line = shift;
push @output, $line;
return 1;
}
sub close {
return 1;
}
sub output {
my $output = join '', @output;
$output =~ s/\n//g;
return $output;
}
}
# test vsistdout redirection
TODO: {
local $TODO = "Fails with GDAL 3.13", 1 if(Geo::GDAL::FFI::GetVersionInfo() >= 3130000);
# create a small layer and copy it to vsistdout with redirection
my $ds = GetDriver($mem_driver)->Create;
my $layer = $ds->CreateLayer({GeometryType => 'None'});
$layer->CreateField(value => 'Integer');
$layer->CreateGeomField(geom => 'Point');
for my $i (1..2) {
my $feature = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$feature->SetField(value => 12);
$feature->SetGeomField(geom => [WKT => "POINT(1 $i)"]);
$layer->CreateFeature($feature);
}
$ds->FlushCache;
my $output = Output->new;
my $gdal = Geo::GDAL::FFI->get_instance;
$gdal->SetWriter($output);
GetDriver('GeoJSON')->Create('/vsistdout')->CopyLayer($layer);
$gdal->CloseWriter;
my $ret = $output->output;
$ret = decode_json $ret;
my $exp = decode_json (get_expected_json_data());
is_deeply ($ret, $exp,
"Redirect vsistdout to write/close methods of a class.");
}
# test Translate
SKIP: {
skip "vsimem test fails with GDAL 3.13", 1 if(Geo::GDAL::FFI::GetVersionInfo() >= 3130000);
my $ds = GetDriver('GTiff')->Create('/vsimem/test.tiff', 10, 10, 1);
my $translated = $ds->Translate('/vsimem/translated.tiff', [-of => 'GTiff']);
ok($translated->GetDriver->GetName eq 'GTiff', "Translate");
}
done_testing();
sub get_expected_json_data {
my $json = <<'EOJSON'
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"id": 0,
"properties": {
"value": 12
},
"geometry": {
"type": "Point",
"coordinates": [1.0, 1.0]
}
}, {
"type": "Feature",
"id": 1,
"properties": {
"value": 12
},
"geometry": {
"type": "Point",
"coordinates": [1.0, 2.0]
}
}
]
}
EOJSON
;
return $json;
}
Geo-GDAL-FFI-0.16/t/vsi.t 0000644 0001755 0001755 00000002507 15044551151 013545 0 ustar pause pause use v5.10;
use strict;
use warnings;
use utf8;
use Carp;
use Encode qw(decode encode);
use Geo::GDAL::FFI;
use Geo::GDAL::FFI::VSI qw/FOpen Mkdir ReadDir/;
use Test::More;
{
Mkdir('/vsimem/x');
FOpen('/vsimem/x/1', 'w');
FOpen('/vsimem/x/2', 'w');
FOpen('/vsimem/x/ä', 'w');
my @dir = ReadDir('/vsimem/x');
is_deeply(\@dir, [1, 2, 'ä'], "Mkdir FOpen ReadDir with UTF8");
}
{
my $f = FOpen('/vsimem/x/1', 'a');
my $n = $f->Write('My test writing something in UTF8. Eli tätä.');
$f->Close;
ok($n == 46, "Write a UTF8 string.");
}
{
my $f = FOpen('/vsimem/x/2', 'a');
my $n = $f->Write("Test writing \0 Perl string");
ok($n == 26, "Write a string containing null.");
$f->Close;
$f = FOpen('/vsimem/x/2', 'r');
my $buf = $f->Read(80);
$n = do {use bytes; length($buf)};
ok($n == 26, "Read a string containing null.");
ok($buf =~ /Perl string/, "Write and Read Perl string.");
}
{
my $f = FOpen('/vsimem/x/1', 'r');
my $buf = $f->Read(80);
my $utf8 = decode(utf8 => $buf);
ok($utf8 =~ /tätä/, "Write Read");
}
#$f = Geo::GDAL::FFI::VSI::File->Open('/vsicurl/http://example.com/');
#my $html = $f->Read(80);
#ok($html =~ /Example Domain/, "Test example.com with vsicurl");
#$f->Close;
done_testing();
Geo-GDAL-FFI-0.16/t/transform.t 0000644 0001755 0001755 00000005253 15045315416 014763 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Geo::GDAL::FFI;
use Test::More;
# test about SRS transformations API by using a simple extent (4 points) in UTM33 -> WGS84
# some systems return high precision values so standardise at 6dp
sub set_precision {
map {sprintf "%.6f", $_} @_;
}
if(1) {
my $source_srs = Geo::GDAL::FFI::SpatialReference->new( EPSG => 4326 );
my $target_srs = Geo::GDAL::FFI::SpatialReference->new( EPSG => 32633 );
my $ct = Geo::GDAL::FFI::OCTNewCoordinateTransformation($$source_srs, $$target_srs);
my @extent = (16.509888, 41.006911, 17.084248, 41.370581);
my @ul = ($extent[0], $extent[1]);
my @lr = ($extent[2], $extent[3]);
my @ur = ($lr[0],$ul[1]);
my @ll = ($ul[0],$lr[1]);
my @result = set_precision (qw/3358768.81711923 3391240.32068776 3348976.84626544 3401215.87353221 2019470.50927319 2094945.30821076 2088830.64307375 2025411.23009774/);
my @x = ($ul[0], $lr[0], $ur[0], $ll[0]);
my @y = ($ul[1], $lr[1], $ur[1], $ll[1]);
my $z = undef;
my $res = Geo::GDAL::FFI::OCTTransform($ct, 4, \@x, \@y, \@$z);
is($res, 1, "Coordinate transformation 3D worked");
is_deeply([set_precision (@x, @y)], \@result, "Checking resulting coordinates");
@x = ($ul[0], $lr[0], $ur[0], $ll[0]);
@y = ($ul[1], $lr[1], $ur[1], $ll[1]);
$z = undef;
my @ps = (0,0,0,0);
$res = Geo::GDAL::FFI::OCTTransformEx($ct, 4, \@x, \@y, \@$z, \@ps);
is($res, 1, "Coordinate transformation 3D with pabSuccess worked");
is_deeply([set_precision (@x, @y)], \@result, "Checking resulting coordinates");
is(scalar @ps, 4, "Resulting pabSuccess is an array of size 4");
is_deeply(\@ps, [1, 1, 1, 1], "Resulting pabSuccess is TRUE x 4" );
@x = ($ul[0], $lr[0], $ur[0], $ll[0]);
@y = ($ul[1], $lr[1], $ur[1], $ll[1]);
$z = undef;
my $t = undef;
@ps = (0,0,0,0);
$res = Geo::GDAL::FFI::OCTTransform4D($ct, 4, \@x, \@y, \@$z, \@$t, \@ps);
is($res, 1, "Coordinate transformation 4D worked");
is_deeply([set_precision (@x, @y), @ps], [@result, 1, 1, 1, 1], "Checking resulting coordinates");
@x = ($ul[0], $lr[0], $ur[0], $ll[0]);
@y = ($ul[1], $lr[1], $ur[1], $ll[1]);
$z = undef;
$t = undef;
@ps = (0,0,0,0);
$res = Geo::GDAL::FFI::OCTTransform4DWithErrorCodes($ct, 4, \@x, \@y, \@$z, \@$t, \@ps);
is($res, 1, "Coordinate transformation 4D worked");
is_deeply([set_precision (@x, @y)], \@result, "Checking resulting coordinates");
is(scalar @ps, 4, "Resulting pabSuccess is an array of size 4");
is_deeply(\@ps, [0, 0, 0, 0], "Resulting pabSuccess is SUCCESS(i.e. 0) x 4" );
}
done_testing();
Geo-GDAL-FFI-0.16/t/threads.t 0000644 0001755 0001755 00000002026 15044551150 014371 0 ustar pause pause use v5.18;
use warnings;
use strict;
use Config;
use Test::More;
BEGIN {
use_ok('Geo::GDAL::FFI', qw/:all/);
}
SKIP: {
skip "skip multi-thread test", 4 unless $Config{useithreads};
use_ok('threads');
use_ok('threads::shared');
use_ok('Thread::Queue');
my $q = Thread::Queue->new();
my @in_thrds = ();
my @out_thrds = ();
my $nt = 10;
for my $i (1..$nt) {
my $t = threads->create(
sub {
while (my $h = $q->dequeue()) {
say "thread out$i: popped $h->{value}";
}
}
);
push @out_thrds, $t;
}
for my $i (1..$nt) {
my $t = threads->create(
sub {
my $v = rand(100);
say "thread in$i: pushed $v";
$q->enqueue({ value => $v });
}
);
push @in_thrds, $t;
}
# try different timing too... :-/
sleep(3);
$q->end();
for my $w (@in_thrds) {
$w->join();
}
for my $w (@out_thrds) {
$w->join();
}
ok(1, "threading seems ok");
}
done_testing();
Geo-GDAL-FFI-0.16/t/sr.t 0000644 0001755 0001755 00000000776 15044551147 013403 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Encode qw(decode encode);
use Geo::GDAL::FFI;
use Test::More;
use Data::Dumper;
use JSON;
use FFI::Platypus::Buffer;
my $gdal = Geo::GDAL::FFI->get_instance();
{
SKIP: {
skip "GDAL support files not found.", 1 if !$gdal->FindFile('gcs.csv');
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
ok($sr->Export('Wkt') =~ /^PROJCS/, 'SpatialReference constructor and WKT export');
}
}
done_testing();
Geo-GDAL-FFI-0.16/t/schema.t 0000644 0001755 0001755 00000003563 15044551146 014213 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Geo::GDAL::FFI qw/GetDriver/;
use Test::More;
use Data::Dumper;
my $mem_driver = Geo::GDAL::FFI::get_memory_driver;
my $schema = {
Name => 'test',
Fields => [
{
Name => 'f1',
Type => 'Integer',
Width => 7,
Ignored => 1,
Default => 23
},
{
Name => 'f2',
Type => 'String',
NotNullable => 1
}
],
GeometryFields => [
{
Name => 'g1',
Type => 'LineString',
NotNullable => 1
},
{
Name => 'g2',
Type => 'Polygon',
Ignored => 1,
}
]
};
my $layer = GetDriver($mem_driver)->Create->CreateLayer($schema);
my $schema2 = {
Name => 'test',
Fields => [
{
Name => 'f1',
Type => 'Integer',
Width => 7,
#Ignored => 1,
Default => 23,
Subtype => 'None',
Justify => 'Undefined',
Precision => 0,
},
{
Name => 'f2',
Type => 'String',
NotNullable => 1,
Subtype => 'None',
Width => 0,
Justify => 'Undefined',
Precision => 0
}
],
GeometryFields => [
{
Name => 'g1',
Type => 'LineString',
NotNullable => 1,
#SpatialReference => undef
},
{
Name => 'g2',
Type => 'Polygon',
#Ignored => 1,
#SpatialReference => undef
}
]
};
$schema = $layer->GetDefn->GetSchema;
#print Dumper $schema;
is_deeply($schema, $schema2, "Create layer based on a schema");
done_testing();
Geo-GDAL-FFI-0.16/t/pdl.t 0000644 0001755 0001755 00000002141 15044551146 013521 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Encode qw(decode encode);
use Geo::GDAL::FFI qw/GetDriver/;
use Test::More;
use Data::Dumper;
use JSON;
use FFI::Platypus::Buffer;
my $band = GetDriver('MEM')->Create('', {Width => 7, Height => 15})->GetBand;
my $t = $band->Read;
$t->[5][3] = 1;
$band->Write($t);
$t->[5][3] = 0;
my $pdl = $band->GetPiddle;
my @s = $pdl->dims;
ok($s[0] == 7 && $s[1] == 15, "Piddle size is right (1).");
ok($pdl->at(3,5) == 1, "Piddle data is ok (1).");
$pdl = $band->GetPiddle(1,2,4,4);
@s = $pdl->dims;
ok($s[0] == 4 && $s[1] == 4, "Piddle size is right (2).");
ok($pdl->at(2,3) == 1, "Piddle data is ok (2).");
$pdl += 1;
$band->Write($t); # zero raster
$band->SetPiddle($pdl);
ok($band->Read->[3][2] == 2, "Data from piddle into band at(0,0).");
$band->Write($t); # zero raster
$band->SetPiddle($pdl,1,2);
ok($band->Read->[5][3] == 2, "Data from piddle into band at(1,2).");
$band->Write($t); # zero raster
$band->SetPiddle($pdl,0,0,7,15);
ok($band->Read->[12][4] == 2, "Data from piddle into band (stretched).");
done_testing();
Geo-GDAL-FFI-0.16/t/open.t 0000644 0001755 0001755 00000002152 15044551144 013703 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Encode qw(decode encode);
use Geo::GDAL::FFI qw/GetDriver Open/;
use Test::More;
use Data::Dumper;
use JSON;
use FFI::Platypus::Buffer;
use Path::Tiny qw/path/;
use Test::TempDir::Tiny;
my $dir = tempdir();
my $testfile = path($dir, 'test.shp');
{
my $ds = GetDriver('ESRI Shapefile')->Create($testfile);
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
my $l = $ds->CreateLayer({Name => 'test', SpatialReference => $sr, GeometryType => 'Point'});
my $d = $l->GetDefn();
my $f = Geo::GDAL::FFI::Feature->new($d);
$l->CreateFeature($f);
}
my $ds;
eval {
$ds = Open($testfile, {
Flags => [qw/READONLY VERBOSE_ERROR/],
AllowedDrivers => [('GML')]
});
};
my @e = split /\n/, $@;
$e[0] =~ s/ at .*//;
ok($@, "Right driver not in AllowedDrivers: ".$e[0]);
eval {
$ds = Open($testfile, {
Flags => [qw/READONLY VERBOSE_ERROR/],
AllowedDrivers => [('GML', 'ESRI Shapefile')]
});
};
ok(!@$, "Require right driver in AllowedDrivers");
done_testing();
Geo-GDAL-FFI-0.16/t/layer.t 0000644 0001755 0001755 00000015444 15044551144 014066 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Geo::GDAL::FFI qw/GetDriver HaveGEOS/;
use Test::More;
use Data::Dumper;
my $mem_driver = Geo::GDAL::FFI::get_memory_driver;
my $schema = {
GeometryType => 'Polygon',
Fields => [
{
Name => 'layer',
Type => 'Integer'
}
]
};
my $layer = GetDriver($mem_driver)->Create->CreateLayer($schema);
my $f = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$f->SetField(layer => 1);
$f->SetGeomField([WKT => 'POLYGON ((1 1, 1 2, 3 2, 3 1, 1 1))']);
$layer->CreateFeature($f);
$schema->{Fields}[0]{Name} = 'method';
my $method = GetDriver($mem_driver)->Create->CreateLayer($schema);
$f = Geo::GDAL::FFI::Feature->new($method->GetDefn);
$f->SetField(method => 2);
$f->SetGeomField([WKT => 'POLYGON ((2 1, 2 2, 4 2, 4 1, 2 1))']);
$method->CreateFeature($f);
{
my $feature_count = $layer->GetFeatureCount;
is $feature_count, 1, 'Got correct feature count';
$feature_count = $layer->GetFeatureCount (1);
is $feature_count, 1, 'Got correct feature count with force arg=true';
}
my $progress;
my $result;
eval {
$result = $layer->Intersection($method, {Progress => sub {$progress = 1}});
};
SKIP: {
skip "No GEOS support in GDAL.", 5 unless HaveGEOS();
ok($progress == 1, "Intersection progress.");
my $count = 0;
$result->ResetReading;
while (my $f = $result->GetNextFeature) {
is($f->GetField('layer'), 1, "Field 1");
is($f->GetField('method'), 2, "Field 2");
my $got;
my $version = Geo::GDAL::FFI::GetVersionInfo() / 100;
if ($version >= 30300) {
$got = $f->GetGeomField->Normalize->AsText;
ok ($got eq 'POLYGON ((2 1,2 2,3 2,3 1,2 1))', "GeomField as expected");
} else {
$got = $f->GetGeomField->AsText;
ok (
# geos 3.9 and pre-3.9 return different vertex orderings
$got eq 'POLYGON ((3 2,3 1,2 1,2 2,3 2))' || # 3.9
$got eq 'POLYGON ((2 2,3 2,3 1,2 1,2 2))', # pre-3.9
"GeomField as expected"
);
}
$count++;
}
is($count, 1, "Intersection result.");
$result = $layer->Union($method);
$result = $layer->SymDifference($method);
$result = $layer->Identity($method);
$result = $layer->Update($method);
$result = $layer->Clip($method);
$result = $layer->Erase($method);
};
# GetName
{
my $name = $layer->GetName;
is ($name, '', 'Got correct default name for anonymous layer');
my $test_name = 'test_name';
my $named_layer = GetDriver($mem_driver)->Create->CreateLayer({Name => $test_name});
$name = $named_layer->GetName;
is ($name, $test_name, 'Got correct name for named layer');
}
my $exp_extent = [1,3,1,2];
is_deeply $layer->GetExtent(0), $exp_extent, 'Got correct layer extent, no forcing';
is_deeply $layer->GetExtent(1), $exp_extent, 'Got correct layer extent when forced';
{
# need to test more than just the spatial index creation
my $ds = GetDriver ('ESRI Shapefile')->Create ('/vsimem/test_sql');
my $layer_name = 'test_sql_layer';
my $layer = $ds->CreateLayer ({
Name => $layer_name,
GeometryType => 'Polygon',
Fields => [
{
Name => 'int_fld',
Type => 'Integer'
},
{
Name => 'str_fld',
Type => 'String',
}
],
});
my $f = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$f->SetField(int_fld => 1);
$f->SetField(str_fld => 'one');
$f->SetGeomField([WKT => 'POLYGON ((1 1, 1 2, 3 2, 3 1, 1 1))']);
$layer->CreateFeature($f);
my $g = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$g->SetField(int_fld => 10);
$g->SetField(str_fld => 'ten');
$g->SetGeomField([WKT => 'POLYGON ((10 10, 10 20, 30 20, 30 10, 10 10))']);
$layer->CreateFeature($g);
my $distinct_items = $ds->ExecuteSQL (
qq{SELECT DISTINCT "str_fld" FROM "$layer_name"}
);
my @items;
$distinct_items->ResetReading;
while (my $feat = $distinct_items->GetNextFeature) {
push @items, $feat->GetField ('str_fld');
}
#diag "ITEMS: " . join ' ', @items;
TODO:
{
#local $TODO = 'sql DISTINCT not yet working, despite following GDAL doc example';
is_deeply (\@items, ['one','ten'], 'got correct distinct items');
}
my $result = eval {
$ds->ExecuteSQL (qq{CREATE SPATIAL INDEX ON "$layer_name"});
};
my $e = $@;
ok (!defined $result, 'ExecuteSQL ran spatial index and undef was returned');
ok (!$e, 'ExecuteSQL did not error');
my $feature_count;
my $filter1 = $ds->ExecuteSQL (
qq{SELECT * FROM "$layer_name" WHERE int_fld > 2},
);
$feature_count = 0;
while (my $feat = $filter1->GetNextFeature) {
$feature_count++;
}
is ($feature_count, 1, 'selected correct number of features');
$filter1->ResetReading;
my $feat = $filter1->GetNextFeature;
is ($feat->GetField ('int_fld'), 10, 'correct field value from selection');
my $filt_poly = Geo::GDAL::FFI::Geometry->new(
WKT => 'POLYGON ((4 0, 4 4, 0 4, 0 0, 4 0))',
);
my $filter2 = $ds->ExecuteSQL (
qq{SELECT * FROM "$layer_name"},
$filt_poly,
);
$feature_count = 0;
while (my $feat = $filter2->GetNextFeature) {
$feature_count++;
}
is ($feature_count, 1, 'spatial filter selected correct number of features');
$filter2->ResetReading;
my $feat2 = $filter2->GetNextFeature;
is ($feat2->GetField ('int_fld'), 1, 'correct field value from spatial filter selection');
# At least one of these needs to be deleted for the next SELECT DISTINCT to work.
# It does not matter if it is before or after the sql call.
#$filter1 = undef;
#$filter2 = undef;
#$distinct_items = undef;
my $distinct_items2 = $ds->ExecuteSQL (
qq{SELECT DISTINCT "str_fld" FROM "$layer_name"}
);
@items = ();
$distinct_items2->ResetReading;
while (my $feat = $distinct_items2->GetNextFeature) {
push @items, $feat->GetField ('str_fld');
}
#diag "ITEMS: " . join ' ', @items;
TODO:
{
local $TODO = 'sql DISTINCT not yet working, despite following GDAL doc example';
is_deeply (\@items, ['one','ten'], 'got correct distinct items');
}
}
{
my $ds = GetDriver($mem_driver)->Create;
my $layer = $ds->CreateLayer($schema);
my $parent = $layer->GetParentDataset;
is ($parent, $ds, 'got parent dataset ref');
}
done_testing();
Geo-GDAL-FFI-0.16/t/geometry.t 0000644 0001755 0001755 00000010744 15201311471 014573 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Encode qw(decode encode);
use Geo::GDAL::FFI qw/GetVersionInfo HaveGEOS/;
use Test::More;
use Data::Dumper;
use JSON;
my $version = GetVersionInfo() / 100;
my $have_geos = HaveGEOS;
{
my $geometry = Geo::GDAL::FFI::Geometry->new(WKT => 'POINT(1 1)');
ok($geometry->GetType eq 'Point', "Create Point from WKT (1).");
ok($geometry->AsText eq 'POINT (1 1)', "Create point from WKT (2).");
}
{
my $geometry = Geo::GDAL::FFI::Geometry->new(WKT => 'POINTM(1 2 3)');
my $type = $geometry->GetType;
ok($type eq 'PointM', "Create PointM from WKT: $type");
my $wkt = $geometry->AsText;
ok($wkt eq 'POINT M (1 2 3)', "Create point from WKT: $wkt");
}
{
my $g = Geo::GDAL::FFI::Geometry->new('Point');
$g->SetPoint(5, 8);
my @p = $g->GetPoint;
ok($p[0] == 5, "Set/GetPoint");
}
SKIP: {
skip "No GEOS support", 1 unless $have_geos;
my $geometry = Geo::GDAL::FFI::Geometry->new(WKT => 'POINT(1 1)');
my $c = $geometry->Centroid;
ok($geometry->AsText eq 'POINT (1 1)', "Centroid");
}
{
my $g = Geo::GDAL::FFI::Geometry->new(WKT => 'POLYHEDRALSURFACE Z ( '.
'((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)), '.
'((0 0 0, 0 1 0, 0 1 1, 0 0 1, 0 0 0)), '.
'((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)), '.
'((1 1 1, 1 0 1, 0 0 1, 0 1 1, 1 1 1)), '.
'((1 1 1, 1 0 1, 1 0 0, 1 1 0, 1 1 1)), '.
'((1 1 1, 1 1 0, 0 1 0, 0 1 1, 1 1 1))) ');
my $p = $g->GetPoints;
ok(@$p == 6, "GetPoints");
$p->[0][0][0][0] = 2;
$g->SetPoints($p);
$p = $g->GetPoints;
ok($p->[0][0][0][0] == 2, "SetPoints");
}
# GetEnvelope
{
my $geom = Geo::GDAL::FFI::Geometry->new(
WKT => 'POLYGON ((0 -1 0, -1 0 0, 0 1 1, 1 0 1, 0 -1 1))',
);
my $envelope = $geom->GetEnvelope;
is_deeply ($envelope, [-1,1,-1,1], 'correct geometry envelope');
my $envelope3d = $geom->GetEnvelope3D;
is_deeply ($envelope3d, [-1,1,-1,1,0,1], 'correct 3D geometry envelope');
my $extent = $geom->GetExtent;
is_deeply ($extent, [-1,-1,1,1], 'correct geometry extent');
my $extent3d = $geom->GetExtent3D;
is_deeply ($extent3d, [-1,-1,0,1,1,1], 'correct 3D geometry extent');
}
SKIP: {
skip "No GEOS support in GDAL.", 5 unless $have_geos;
skip "Needs version >= 3.0", 1 unless $version >= 30000;
my $wkt = 'POLYGON ((0 -1,-1 0,0 1,1 0,0 -1))';
my $geom = Geo::GDAL::FFI::Geometry->new(WKT => $wkt);
my $test = $geom->MakeValid(METHOD => 'LINEWORK');
ok($wkt eq $test->AsText);
}
SKIP: {
skip "No GEOS support in GDAL.", 5 unless $have_geos;
skip "Needs version >= 3.3", 1 unless $version >= 30300;
my $wkt = 'POLYGON ((0 -1,-1 0,0 1,1 0,0 -1))';
my $geom = Geo::GDAL::FFI::Geometry->new(WKT => $wkt);
my $test = $geom->Normalize();
ok($test->AsText eq 'POLYGON ((-1 0,0 1,1 0,0 -1,-1 0))');
}
SKIP: {
skip "No GEOS support in GDAL.", 5 unless $have_geos;
skip "Needs version >= 3.6", 1 unless $version >= 30600;
my $wkt = 'MULTIPOINT ((0 -1),(-1 0),(0 1),(1 0),(0 -1))';
my $geom = Geo::GDAL::FFI::Geometry->new(WKT => $wkt);
my $test = $geom->ConcaveHull(0.5)->Normalize;
is($test->AsText, 'POLYGON ((-1 0,0 1,1 0,0 -1,-1 0))', 'ConcaveHull');
}
SKIP: {
skip "No GEOS support in GDAL.", 5 unless $have_geos;
skip "Needs version >= 3.10", 1 unless $version >= 31000;
my $wkt = 'MULTIPOLYGON (((0 -10, -10 0, 0 10, 10 0, 0 -10)))';
my $geom = Geo::GDAL::FFI::Geometry->new(WKT => $wkt);
my $test = $geom->Segmentize(5)->Normalize;
my $exp = <<'EOE'
MULTIPOLYGON ((
(-10 0,-6.66666666666667 3.33333333333333,-3.33333333333333 6.66666666666667,
0 10,3.33333333333333 6.66666666666667,6.66666666666667 3.33333333333333,
10 0,6.66666666666667 -3.33333333333333,3.33333333333333 -6.66666666666667,
0 -10,-3.33333333333333 -6.66666666666667,-6.66666666666667 -3.33333333333333,
-10 0)))';
EOE
;
$exp = Geo::GDAL::FFI::Geometry->new(WKT => $exp);
is($test->AsText, $exp->AsText, 'Segmentize');
}
{
skip "No GEOS support in GDAL.", 5 unless $have_geos;
my $wkt = 'MULTIPOLYGON (((0 0, 0 1, 1 1, 1 0, 0 0)),((1 0, 1 1, 2 1, 2 0, 1 0)))';
my $geom = Geo::GDAL::FFI::Geometry->new(WKT => $wkt);
my $test = $geom->UnaryUnion()->Normalize;
is($test->AsText, 'POLYGON ((0 0,0 1,1 1,2 1,2 0,1 0,0 0))', 'UnaryUnion');
}
done_testing();
Geo-GDAL-FFI-0.16/t/dataset_rasterize.t 0000644 0001755 0001755 00000012431 15044551142 016456 0 ustar pause pause use 5.010;
use strict;
use warnings;
use Geo::GDAL::FFI;
use Test::More;
use Test::TempDir::Tiny;
use Path::Tiny qw/path/;
local $| = 1;
test_VectorTranslate();
test_NearBlack();
test_Warp();
test_Rasterize();
sub test_VectorTranslate {
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
my $source_ds = Geo::GDAL::FFI::GetDriver('ESRI Shapefile')
->Create('/vsimem/test.shp');
my $layer = $source_ds->CreateLayer({
Name => 'test',
SpatialReference => $sr,
GeometryType => 'Polygon',
Fields => [
{
Name => 'name',
Type => 'String'
}
]
});
my $f = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$f->SetField(name => 'a');
my $g = Geo::GDAL::FFI::Geometry->new('Polygon');
my $poly = 'POLYGON ((1 2, 2 2, 2 1, 1 1, 1 2))';
$f->SetGeomField([WKT => $poly]);
$layer->CreateFeature($f);
my $result = eval {
$source_ds->VectorTranslate ({
Destination => '/vsimem/test_VectorTranslate',
Options => [-f => "GML"],
})
};
my $e = $@;
diag $e if $e;
ok (!$e, 'Ran basic VectorTranslate call without raising exception');
}
sub test_NearBlack {
my $raster = get_test_raster();
my $nb = eval {
$raster->NearBlack({
Destination => '/vsimem/test_near_black',
Options => [
'-white',
],
})
};
my $e = $@;
diag $e if $e;
ok (!$e, 'ran NearBlack without raising exception');
}
sub test_Warp {
SKIP: {
skip 'need to ensure Proj4 is available before running this test';
my $raster = get_test_raster();
# should use a coord sys with a domain that contains the data...
my $srs = 'EPSG:3577';
my $warped = eval {
$raster->Warp({
Destination => '/vsimem/test_warp',
Options => [
-t_srs => $srs,
],
})
};
my $e = $@;
diag $e if $e;
ok (!$e, 'ran Warp without exception');
# more tests needed
}
}
sub test_Rasterize {
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
my $source_ds = Geo::GDAL::FFI::GetDriver('ESRI Shapefile')
->Create('/vsimem/test.shp');
my $layer = $source_ds->CreateLayer({
Name => 'test',
SpatialReference => $sr,
GeometryType => 'Polygon',
Fields => [
{
Name => 'name',
Type => 'String'
}
]
});
my $f = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$f->SetField(name => 'a');
my $g = Geo::GDAL::FFI::Geometry->new('Polygon');
my $poly = 'POLYGON ((1 2, 2 2, 2 1, 1 1, 1 2))';
$f->SetGeomField([WKT => $poly]);
$layer->CreateFeature($f);
my $x_min = 0;
my $y_max = 2;
my $pixel_size = 1;
my $fname = '/vsimem/test_' . time() . '.tiff';
my $target_ds = Geo::GDAL::FFI::GetDriver('GTiff')->Create($fname, 3, 2);
my $transform = [$x_min, $pixel_size, 0, $y_max, 0, -$pixel_size];
$target_ds->SetGeoTransform($transform);
$target_ds->SetProjectionString($sr->Export('Wkt'));
# void context was causing crash due to destroy methods
$source_ds->Rasterize({
Destination => $target_ds,
Options => [
-b => 1,
-burn => 1,
-at,
],
});
my $band_r1 = $target_ds->GetBand;
my $arr_ref = $band_r1->Read;
ok (1, 'Read band data without crashing');
$fname = '/vsimem/test_' . (time()+1) . '.tiff';
my $target_ds2 = Geo::GDAL::FFI::GetDriver('GTiff')->Create($fname, 3, 2);
my $transform2 = [$x_min, $pixel_size, 0, $y_max, 0, -$pixel_size];
$target_ds2->SetGeoTransform($transform2);
$target_ds2->SetProjectionString($sr->Export('Wkt'));
# make sure we get a ref back
my $target_ds2b = eval {
$source_ds->Rasterize({
Destination => $target_ds2,
Options => [
-b => 1,
-burn => 1,
-at,
],
})
};
my $e = $@;
ok ($e, 'Rasterize dies if called in non-void context and destination is set');
}
sub get_test_raster {
my $dir = tempdir();
# my $name = 'test_ras' . time() + rand() . '.tiff';
my $tiff_file = path ($dir, 'test.tiff');
my $tiff = Geo::GDAL::FFI::GetDriver('GTiff')->Create($tiff_file, 3, 2);
my $ogc_wkt =
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,'.
'AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,'.
'AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,'.
'AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]';
$tiff->SetProjectionString($ogc_wkt);
my $transform = [10,2,0,20,0,3];
$tiff->SetGeoTransform($transform);
my $data = [[0,1,2],[3,4,5]];
$tiff->GetBand->Write($data);
return $tiff;
}
done_testing();
Geo-GDAL-FFI-0.16/t/dataset.t 0000644 0001755 0001755 00000004254 15045315416 014375 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Carp;
use Geo::GDAL::FFI qw/GetDriver HaveGEOS/;
use Test::More;
use Test::Exception;
use Data::Dumper;
use Test::TempDir::Tiny;
use Path::Tiny qw/path/;
my $dir = tempdir();
my $gpkg_file = path ($dir, 'test.gpkg');
my $ds = GetDriver('GPKG')->Create($gpkg_file);
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
my @layernames;
foreach my $i (1..3) {
my $name = "test$i";
push @layernames, $name;
my $l = $ds->CreateLayer({
Name => $name,
SpatialReference => $sr,
GeometryType => 'Point',
});
my $d = $l->GetDefn();
my $f = Geo::GDAL::FFI::Feature->new($d);
$l->CreateFeature($f);
}
is ($ds->GetLayerCount, 3, 'Got expected number of layers');
{
my $ds2 = Geo::GDAL::FFI::Open($gpkg_file);
for my $i (0 .. $ds2->GetLayerCount - 1) {
my $layer = $ds2->GetLayer($i);
ok($layer, "Got layer $i");
is ($layer->GetName, $layernames[$i], 'Layer has expected name');
}
for my $i (0 .. $ds2->GetLayerCount - 1) {
my $layer = $ds2->GetLayerByIndex($i);
ok($ds2, "Got layer by index $i");
is ($layer->GetName, $layernames[$i], 'Layer has expected name');
}
for my $i (0 .. $ds2->GetLayerCount - 1) {
my $name = $layernames[$i];
my $layer = $ds2->GetLayerByName($name);
ok($ds2, "Got layer by name $name, index $i");
is ($layer->GetName, $name, 'Layer has expected name');
}
is_deeply scalar $ds2->GetLayerNames, \@layernames, "GetLayerNames array matches";
}
dies_ok (
sub {$ds->GetLayer ('not_exists')},
'GetLayer exception for non-existent layer name',
);
dies_ok (
sub {$ds->GetLayer (23)},
'GetLayer exception for too large index',
);
dies_ok (
sub {$ds->GetLayer (-1)},
'GetLayer exception for negative index',
);
if(0) { # dataset metadata test
$ds->SetMetadata({'d' => {'a' => 'b'}});
my $md = $ds->GetMetadata();
for my $d (keys %$md) {
say 'domain ',$d;
for (keys %{$md->{$d}}) {
say $_, '=>', $md->{$d}{$_};
}
}
}
done_testing();
Geo-GDAL-FFI-0.16/t/01.t 0000644 0001755 0001755 00000050156 15044551140 013165 0 ustar pause pause use v5.10;
use strict;
use warnings;
use Config;
use Carp;
use Encode qw(decode encode);
use Test::More;
use Data::Dumper;
use JSON;
use Test::TempDir::Tiny;
use Path::Tiny qw/path/;
BEGIN { use_ok('Geo::GDAL::FFI', qw/:all/); }
my $mem_driver = Geo::GDAL::FFI::get_memory_driver;
if(1){
Geo::GDAL::FFI::UnsetErrorHandling();
print STDERR "test a - GDAL error messages without Geo::GDAL::FFI error handling:\n";
my $err_cat = $Geo::GDAL::FFI::Debug;
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "A GDAL Debug message.");
$err_cat = $Geo::GDAL::FFI::Warning;
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "A GDAL Warning message.");
$err_cat = $Geo::GDAL::FFI::Failure;
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "A GDAL Failure error message.");
print STDERR "Fatal GDAL error ends the program even when run inside eval.\n";
# Fatal error dumps core
#eval {
# $err_cat = $Geo::GDAL::FFI::Fatal;
# Geo::GDAL::FFI::CPLError(
# $err_cat, 1, "This is GDAL Fatal error ($Geo::GDAL::FFI::Fatal) without Geo::GDAL::FFI error handling...");
#};
#print STDERR "run in Perl eval {};\n";
Geo::GDAL::FFI::SetErrorHandling();
print STDERR "test b - GDAL error messages with Geo::GDAL::FFI error handling:\n";
$err_cat = $Geo::GDAL::FFI::Debug;
print STDERR "GDAL Debug message requires \$Geo::GDAL::FFI::DEBUG set to true.\n";
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "You don't see this.");
$Geo::GDAL::FFI::DEBUG = 1;
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "\$Geo::GDAL::FFI::DEBUG is now true.\n");
$Geo::GDAL::FFI::DEBUG = 0;
$err_cat = $Geo::GDAL::FFI::Warning;
$SIG{'__WARN__'} = sub {
print STDERR "Perl warning: $_[0]";
};
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "A GDAL Warning is converted into a Perl warn call.");
$err_cat = $Geo::GDAL::FFI::Failure;
Geo::GDAL::FFI::CPLError(
$err_cat, 1, "A GDAL Failure.");
print STDERR "GDAL Failures are stored in \@Geo::GDAL::FFI::errors:\n@Geo::GDAL::FFI::errors\n";
}
# test the singleton
if(1){
my $gdal = Geo::GDAL::FFI->get_instance();
$gdal->{favourite_animal} = 'llama';
my $gdal2 = Geo::GDAL::FFI->get_instance();
ok($gdal->{favourite_animal} eq $gdal2->{favourite_animal}, "Instance is a singleton 1/2.");
$gdal2 = Geo::GDAL::FFI->new();
ok($gdal->{favourite_animal} eq $gdal2->{favourite_animal}, "Instance is a singleton 2/2.");
}
# test unavailable function
if(1){
my $gdal = Geo::GDAL::FFI->get_instance();
my $can = $gdal->can('is_not_available');
ok(!$can, "Can't call missing functions.");
}
# test error handler:
if(1){
eval {
my $ds = Open('itsnotthere.tiff');
};
ok(defined $@, "Got error: '$@'.");
}
# test CSL
if(1){
ok(Geo::GDAL::FFI::CSLCount(0) == 0, "empty CSL");
my @list;
my $csl = Geo::GDAL::FFI::CSLAddString(0, 'foo');
for my $i (0..Geo::GDAL::FFI::CSLCount($csl)-1) {
push @list, Geo::GDAL::FFI::CSLGetField($csl, $i);
}
ok(@list == 1 && $list[0] eq 'foo', "list with one string: '@list'");
}
# test file finder
if(1){
my $gdal_data_dir = GetConfigOption(GDAL_DATA => '');
SKIP: {
skip "GDAL (Alien::gdal) is not properly installed; GDAL support files are not available.", 3 unless $gdal_data_dir;
my $target_file= 'stateplane.csv';
my $path = FindFile($target_file);
ok(defined $path, "GDAL support files found.");
my $version = Geo::GDAL::FFI::GetVersionInfo('SEMANTIC');
say STDERR "FYI: Your GDAL is version $version";
say STDERR "FYI: GDAL_DATA = $gdal_data_dir";
if (!$path) {
# what's wrong with GDAL_DATA??
if (opendir(my $dh, $gdal_data_dir)) {
my @contents = grep { -f "$gdal_data_dir/$_" } readdir($dh);
closedir $dh;
@contents = sort @contents;
say STDERR "Contents of GDAL_DATA: @contents";
} else {
say STDERR "Can't opendir $gdal_data_dir: $!";
}
}
PopFinderLocation(); #FinderClean;
my $path2 = FindFile($target_file);
ok(not(defined $path2), "GDAL support files not found after popping finder.");
$path =~ s/[\w.]+$//;
PushFinderLocation($path);
$path = FindFile($target_file);
ok(defined $path, "GDAL support files found when working path inserted.");
}
}
# test VersionInfo
if(1){
my $info = GetVersionInfo();
ok($info, "Got info: '$info'.");
}
# test driver count
if(1){
my $n = GetDrivers();
ok($n > 0, "Have $n drivers.");
}
# test metadata
if(1){
my $dr;
eval {$dr = GetDriver('NITF');};
SKIP: {
skip "metadata tests. NITF driver not found." unless defined $dr;
my $ds = $dr->Create('/vsimem/test.nitf', 10);
my @d = $ds->GetMetadataDomainList;
ok(@d > 0, "GetMetadataDomainList"); # DERIVED_SUBDATASETS NITF_METADATA CGM
my %d = $ds->GetMetadata;
is_deeply([sort keys %d], [sort @d], "GetMetadata");
%d = $ds->GetMetadata('NITF_METADATA');
@d = keys %d; # NITFFileHeader NITFImageSubheader
ok(@d == 2, "GetMetadata(\$domain)");
$ds->SetMetadata({x => {a => 'b'}});
%d = $ds->GetMetadata('x');
is_deeply(\%d, {a => 'b'}, "SetMetadata");
}
}
# test progress function
if(1){
my $dr = GetDriver('GTiff');
my $ds = $dr->Create('/vsimem/test.tiff', 10);
my $was_at_fct = 0;
my $progress = sub {
my ($fraction, $msg, $data) = @_;
#say STDERR "$fraction $data";
++$was_at_fct;
};
my $data = 'whoa';
my $ds2 = $dr->Create('/vsimem/copy.tiff', {Source => $ds, Progress => $progress, ProgressData => \$data});
ok($was_at_fct > 0, "Progress callback called $was_at_fct times.");
}
# test Info
if(1){
my $dr = GetDriver('GTiff');
my $ds = $dr->Create('/vsimem/test.tiff', 10);
my $info = decode_json $ds->GetInfo(['-json']);
ok($info->{files}[0] eq '/vsimem/test.tiff', "Info");
}
# test dataset
if(1){
my $ffi = Geo::GDAL::FFI->new;
my $dr = GetDriver('GTiff');
my $ds = $dr->Create('/vsimem/test.tiff', 10);
my $ogc_wkt =
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,'.
'AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,'.
'AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,'.
'AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],'.
'AUTHORITY["EPSG","4326"]]';
# Handle Alien::gdal version issues due to PkgConfig, where version is a '${CONFIG_VERSION}' literal
# We should not be seeing version 2 in the wild now anyway.
if ($ffi->{gdal}->version =~ /^2/) {
$ogc_wkt =
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,'.
'AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,'.
'AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,'.
'AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]';
}
$ds->SetProjectionString($ogc_wkt);
my $p = $ds->GetProjectionString;
is($p, $ogc_wkt, "Set/get projection string");
my $transform = [10,2,0,20,0,3];
$ds->SetGeoTransform($transform);
my $inv = [0,0,0,0,0,0];
ok(Geo::GDAL::FFI::GDALInvGeoTransform($transform, $inv), "Invert geotransform returned true");
# avoid precision isssues. 6dp should be sufficient.
is_deeply (
[map {sprintf "%.6f", $_} @$inv],
[map {sprintf "%.6f", $_} (-5, 0.5, 0, -6 - 2/3, 0, 1/3)],
"Invert geotransform result",
);
my ($x, $y);
Geo::GDAL::FFI::GDALApplyGeoTransform($transform,5,5,\$x,\$y);
is($x, 20, "Applied geotransform to pixel coords, x");
is($y, 35, "Applied geotransform to pixel coords, y");
my $t = $ds->GetGeoTransform;
is_deeply($t, $transform, "Set/get geotransform");
}
# test band
if(1){
my $dr = GetDriver('GTiff');
my $ds = $dr->Create('/vsimem/test.tiff', 256);
my $b = $ds->GetBand;
#say STDERR $b;
my @size = $b->GetBlockSize;
#say STDERR "block size = @size";
is_deeply (\@size, [256, 32], "Band block size");
my @data = (
[1, 2, 3],
[4, 5, 6]
);
$b->Write(\@data);
my $data = $b->Read(0, 0, 3, 2);
is_deeply(\@data, $data, "Raster i/o");
$ds->FlushCache;
my $block = $b->ReadBlock();
# for my $ln (@$block) {
#say STDERR "@$ln";
# }
# ok(@{$block->[0]} == 256 && @$block == 32 && $block->[1][2] == 6, "Read block ($block->[1][2])");
is (scalar @{$block->[0]}, 256, "Read block size x");
is (scalar @$block, 32, "Read block size y");
is ($block->[1][2], 6, "Read block (\$block->[1][2])");
$block->[1][2] = 7;
$b->WriteBlock($block);
$block = $b->ReadBlock();
is($block->[1][2], 7, "Write block (\$block->[1][2])");
$b->SetCategoryNames('a', 'b');
my @names = $b->GetCategoryNames;
is_deeply(\@names, ['a', 'b'], "Set and get raster category names (got '@names').");
my $v = $b->GetNoDataValue;
is($v, undef, "Get nodata value.");
$b->SetNoDataValue(13);
$v = $b->GetNoDataValue;
is($v, 13, "Set nodata value.");
$b->SetNoDataValue();
$v = $b->GetNoDataValue;
is($v, undef, "Delete nodata value.");
# the color table test with GTiff fails with
# Cannot modify tag "PhotometricInterpretation" while writing at (a line afterwards this).
# should investigate why
#$b->SetColorTable([[1,2,3,4],[5,6,7,8]]);
if(0){ # band metadata test
$b->SetMetadata({'d' => {'a' => 'b'}});
my $md = $b->GetMetadata();
for my $d (keys %$md) {
say 'domain ',$d;
for (keys %{$md->{$d}}) {
say $_, '=>', $md->{$d}{$_};
}
}
}
}
if(1){
my $dr = GetDriver('MEM');
my $ds = $dr->Create('', 10);
my $b = $ds->GetBand;
my $table = [[1,2,3,4],[5,6,7,8]];
$b->SetColorTable($table);
my $t = $b->GetColorTable;
is_deeply($t, $table, "Set/get color table");
$b->SetColorInterpretation('PaletteIndex');
$ds->FlushCache;
}
# test creating a shapefile
if(1){
my $dir = tempdir();
my $testfile = path($dir, 'test.shp');
my $dr = GetDriver('ESRI Shapefile');
my $ds = $dr->Create($testfile);
my @sr = ();
if (FindFile('gcs.csv')) { # should be version checked? GDAL 3 does not use gcs.csv
@sr = (SpatialReference => Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067));
}
my $l = $ds->CreateLayer({Name => 'test', GeometryType => 'Point', @sr});
my $d = $l->GetDefn();
my $f = Geo::GDAL::FFI::Feature->new($d);
$l->CreateFeature($f);
undef $l; # otherwise $ds is not flushed due to parent ref
$ds = Open($testfile);
$l = $ds->GetLayer;
$d = $l->GetDefn();
is($d->GetGeomType, 'Point', "Create point shapefile and open it.");
}
# test field definitions
if(1){
my $f = Geo::GDAL::FFI::FieldDefn->new({Name => 'test', Type => 'Integer'});
is($f->GetName, 'test', "Field definition: get name");
is($f->GetType, 'Integer', "Field definition: get type");
$f->SetName('test2');
is($f->GetName, 'test2', "Field definition: name");
$f->SetType('Real');
is($f->GetType, 'Real', "Field definition: type");
$f->SetSubtype('Float32');
is($f->GetSubtype, 'Float32', "Field definition: subtype");
$f->SetJustify('Left');
is($f->GetJustify, 'Left', "Field definition: Justify");
$f->SetWidth(10);
is($f->GetWidth, 10, "Field definition: Width");
$f->SetPrecision(10);
is($f->GetPrecision, 10, "Field definition: Precision");
$f->SetIgnored;
ok($f->IsIgnored, "Field definition: Ignored ");
$f->SetIgnored(0);
ok(!$f->IsIgnored, "Field definition: not Ignored");
$f->SetNullable(1);
ok($f->IsNullable, "Field definition: Nullable");
$f->SetNullable;
ok(!$f->IsNullable, "Field definition: Nullable");
$f = Geo::GDAL::FFI::GeomFieldDefn->new({Name => 'test', GeometryType => 'Point'});
is($f->GetName, 'test', "Geometry field definition: get name");
is($f->GetType, 'Point', "Geometry field definition: get type");
$f->SetName('test2');
is($f->GetName, 'test2', "Geometry field definition: name");
$f->SetType('LineString');
is($f->GetType, 'LineString', "Geometry field definition: type");
$f->SetIgnored;
ok($f->IsIgnored, "Geometry field definition: Ignored");
$f->SetIgnored(0);
ok(!$f->IsIgnored, "Geometry field definition: not Ignored");
$f->SetNullable(1);
ok($f->IsNullable, "Geometry field definition: Nullable");
$f->SetNullable;
ok(!$f->IsNullable, "Geometry field definition: Nullable");
}
# test feature definitions
if(1){
my $d = Geo::GDAL::FFI::FeatureDefn->new;
is($d->GetFieldDefns, 0, "GetFieldCount");
is($d->GetGeomFieldDefns, 1, "GetGeomFieldCount ".(scalar $d->GetGeomFieldDefns));
$d->SetGeometryIgnored(1);
ok($d->IsGeometryIgnored, "IsGeometryIgnored");
$d->SetGeometryIgnored(0);
ok(!$d->IsGeometryIgnored, "IsGeometryIgnored");
$d->SetStyleIgnored(1);
ok($d->IsStyleIgnored, "IsStyleIgnored");
$d->SetStyleIgnored(0);
ok(!$d->IsStyleIgnored, "IsStyleIgnored");
$d->SetGeomType('Polygon');
is($d->GetGeomType, 'Polygon', "GeomType");
$d->AddFieldDefn(Geo::GDAL::FFI::FieldDefn->new({Name => 'test', Type => 'Integer'}));
is($d->GetFieldDefns, 1, "GetFieldCount");
$d->DeleteFieldDefn(0);
is($d->GetFieldDefns, 0, "DeleteFieldDefn");
$d->AddGeomFieldDefn(Geo::GDAL::FFI::GeomFieldDefn->new({Name => 'test', GeometryType => 'Point'}));
is($d->GetGeomFieldDefns, 2, "GetGeomFieldCount");
$d->DeleteGeomFieldDefn(1);
is($d->GetGeomFieldDefns, 1, "DeleteGeomFieldDefn");
}
# test creating a geometry object
if(1){
my $g = Geo::GDAL::FFI::Geometry->new('Point');
my $wkt = $g->AsText;
is($wkt, 'POINT EMPTY', "Got WKT: '$wkt'.");
$g = Geo::GDAL::FFI::Geometry->new(WKT => 'POINT (1 2)');
is($g->AsText, 'POINT (1 2)', "Import from WKT");
is($g->GetPointCount, 1, "Point count");
my @p = $g->GetPoint;
is_deeply (\@p, [1,2], 'Get point');
$g->SetPoint(2, 3, 4, 5);
@p = $g->GetPoint;
ok(@p == 2 && $p[0] == 2 && $p[1] == 3, "Set point: @p");
is_deeply(\@p, [2,3], "Set point: @p");
$g = Geo::GDAL::FFI::Geometry->new('PointZM');
is($g->GetType, 'PointZM', "Geom constructor respects M & Z");
$g = Geo::GDAL::FFI::Geometry->new('Point25D');
is($g->GetType, 'Point25D', "Geom constructor respects M & Z");
$g = Geo::GDAL::FFI::Geometry->new('PointM');
is($g->GetType, 'PointM', "Geom constructor respects M & Z");
$wkt = $g->AsText;
is($wkt, 'POINT M EMPTY', "Got WKT: '$wkt'.");
$g = Geo::GDAL::FFI::Geometry->new(WKT => 'POINTM (1 2 3)');
is($g->AsText, 'POINT M (1 2 3)', "Import PointM from WKT");
}
# test features
if(1){
my $d = Geo::GDAL::FFI::FeatureDefn->new();
# geometry type checking is not implemented in GDAL
#$d->SetGeomType('PointM');
$d->AddGeomFieldDefn(Geo::GDAL::FFI::GeomFieldDefn->new({Name => 'test2', GeometryType => 'LineString'}));
my $f = Geo::GDAL::FFI::Feature->new($d);
is($d->GetGeomFieldDefns, 2, "GetGeometryCount");
#GetGeomFieldDefnRef
my $g = Geo::GDAL::FFI::Geometry->new('PointM');
$g->SetPoint(1,2,3,4);
$f->SetGeomField($g);
my $h = $f->GetGeomField();
is($h->AsText, 'POINT M (1 2 4)', "GetGeometry");
$g = Geo::GDAL::FFI::Geometry->new('LineString');
$g->SetPoint(0, 5,6,7,8);
$g->SetPoint(1, [7,8]);
$f->SetGeomField(1 => $g);
$h = $f->GetGeomField(1);
is($h->AsText, 'LINESTRING (5 6,7 8)', "2nd geom field");
}
# test setting field
if(1){
my $types = \%Geo::GDAL::FFI::field_types;
my $d = Geo::GDAL::FFI::FeatureDefn->new();
for my $t (sort {$types->{$a} <=> $types->{$b}} keys %$types) {
$d->AddFieldDefn(Geo::GDAL::FFI::FieldDefn->new({Name => $t, Type => $t}));
}
my $f = Geo::GDAL::FFI::Feature->new($d);
my $n = 'Integer';
my $x = $f->IsFieldSet($n) ? 'set' : 'not set';
is($x, 'not set', "Not set");
$x = $f->IsFieldNull($n) ? 'null' : 'not null';
is($x, 'not null', "Not null");
$f->SetField($n, undef);
$x = $f->IsFieldSet($n) ? 'set' : 'not set';
is($x, 'set', "Set");
$x = $f->IsFieldNull($n) ? 'null' : 'not null';
is($x, 'null', "Null");
$f->SetField($n);
$x = $f->IsFieldSet($n) ? 'set' : 'not set';
is($x, 'not set', "Not set");
$x = $f->IsFieldNull($n) ? 'null' : 'not null';
is($x, 'not null', "Not null");
# scalar types
$f->SetField($n, 13);
$x = $f->GetField($n);
is($x, 13, "Set/get Integer field: $x");
SKIP: {
skip "64 bit integers not supported in this Perl.",1 unless $Config{use64bitint} eq 'define';
$n = 'Integer64';
$f->SetField($n, 0x90000001);
$x = $f->GetField($n);
is($x, 0x90000001, "Set/get Integer64 field: $x");
}
$f->SetField(Real => 1.123);
$x = $f->GetField('Real');
$x = sprintf("%.3f", $x);
is($x, '1.123', "Set/get Real field: $x");
my $s = decode utf8 => 'åäö';
$f->SetField(String => $s);
$x = $f->GetField(String => 'utf8');
is($x, $s, "Set/get String field: $x");
# WideString not tested
#$f->SetFieldBinary(Binary}, 1);
my @s = (13, 21, 7, 5);
$f->SetField(IntegerList => @s);
my @x = $f->GetField('IntegerList');
is_deeply(\@x, \@s, "Set/get IntegerList field: @x");
SKIP: {
skip "64 bit integers not supported in this Perl.",1 unless $Config{use64bitint} eq 'define';
$n = 'Integer64List';
@s = (0x90000001, 21, 7, 5);
$f->SetField($n, @s);
@x = $f->GetField($n);
is_deeply(\@x, \@s, "Set/get Integer64List field: @s => @x");
}
@s = (3, 21.2, 7.4, 5.5);
$f->SetField(RealList => @s);
@x = $f->GetField('RealList');
for (@s) {
$_ = sprintf("%.3f", $_);
}
for (@x) {
$_ = sprintf("%.3f", $_);
}
is_deeply(\@x, \@s, "Set/get DoubleList field: @x");
@s = ('a', 'gdal', 'perl');
$f->SetField(StringList => @s);
@x = $f->GetField('StringList');
is_deeply(\@x, \@s, "Set/get StringList field: @x");
@s = (1962, 4, 23);
$f->SetField(Date => @s);
@x = $f->GetField('Date');
is_deeply(\@x, \@s, "Set/get Date field: @x");
$n = 'Time';
@s = (15, 23, 23.34, 1);
$f->SetField($n, @s);
@x = $f->GetField($n);
is_deeply(\@x, \@s, "Set/get Time field: @x");
$n = 'DateTime';
@s = (1962, 4, 23, 15, 23, 23.34, 1);
$f->SetField($n, @s);
@x = $f->GetField($n);
is_deeply(\@x, \@s, "Set/get DateTime field: @x");
# Binary => 8,
@s = (1962, 4, 23);
$f->SetField(Date => @s);
@x = $f->GetField('Date');
is_deeply(\@x, \@s, "Set/get Date field: @x");
}
# test layer feature manipulation
if(1){
my $dr = GetDriver($mem_driver);
my $ds = $dr->Create({Name => 'test'});
my @sr = ();
if (FindFile('stateplane.csv')) {
@sr = (SpatialReference => Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067));
}
my $l = $ds->CreateLayer({Name => 'test', GeometryType => 'Point', @sr});
$l->CreateField(Geo::GDAL::FFI::FieldDefn->new({Name => 'int', Type => 'Integer'}));
my $f = Geo::GDAL::FFI::Feature->new($l->GetDefn);
$f->SetField(int => 5);
my $g = Geo::GDAL::FFI::Geometry->new('Point');
$g->SetPoint(3, 5);
$f->SetGeomField($g);
$l->CreateFeature($f);
my $fid = $f->GetFID;
is($fid, 0, "FID of first feature");
$f = $l->GetFeature($fid);
is($f->GetField('int'), 5, "Field was set");
is($f->GetGeomField->AsText, 'POINT (3 5)', "Geom Field was set");
}
done_testing();
Geo-GDAL-FFI-0.16/t/00-diag-aliens.t 0000644 0001755 0001755 00000006322 15131644472 015343 0 ustar pause pause use strict;
use warnings;
use Test::More;
SKIP: {
eval { require Alien::gdal };
skip "Alien::gdal not installed", 1 if $@;
diag '';
diag 'Aliens:';
my %alien_versions;
my @aliens = qw /
Alien::gdal Alien::geos::af Alien::sqlite
Alien::proj Alien::libtiff Alien::spatialite
Alien::freexl
/;
my %optional = map {$_ => 1} qw /Alien::spatialite Alien::freexl/;
# use our own in case List::Util is not installed, although it should be...
my $longest_name = 0;
foreach my $len (map {length} @aliens) {
$longest_name = $len if $len > $longest_name;
}
foreach my $alien (@aliens) {
eval "require $alien; 1";
if ($@) {
#diag "$alien not installed";
my $optional_text = $optional{$alien} ? "(optional module)" : '';
diag sprintf "%-${longest_name}s: not installed $optional_text", $alien;
next;
}
diag sprintf "%-${longest_name}s: version:%7s, install type: %s",
$alien,
$alien->version // 'unknown',
$alien->install_type;
$alien_versions{$alien} = $alien->version;
}
if ($alien_versions{'Alien::gdal'} ge 3) {
if ($alien_versions{'Alien::proj'} lt 7) {
diag 'Alien proj is <7 when gdal >=3';
}
}
else {
if ($alien_versions{'Alien::proj'} ge 7) {
diag 'Alien proj is >=7 when gdal <3';
}
}
# Crude and incomplete way of limiting to linux
# bsd ldd has different args
my $have_ldd = ($^O ne 'MSWin32' && $^O !~ /darwin/i && $^O !~ /bsd|dragonfly/) && !!`ldd --help`;
if (Alien::gdal->install_type eq 'share' && $have_ldd) {
my $dylib = Alien::gdal->dist_dir . '/lib/libgdal.so';
if (-e $dylib) {
my @deps = `ldd $dylib`;
my %collated;
# https://gdal.org/en/latest/development/building_from_source.html#conflicting-proj-libraries
# blunt approach but proj is the main culprit and there seem to be some legit double ups.
foreach my $line (@deps) {
$line =~ s/[\r\n]+//g;
# diag $line;
$line =~ s/^\s+//;
my ($lib, $path) = split /\s+=>\s+/, $line, 2;
# diag "$lib --- $path";
next if !$path;
$lib =~ s/\.so.+//;
next if $path =~ m{^/lib};
my $aref = $collated{$lib} //= [];
push @$aref, $path;
}
foreach my $key (keys %collated) {
my $aref = $collated{$key} // [];
if (@$aref <= 1) {
delete $collated{$key};
}
}
# my $res = is (scalar keys %collated, 0, "No duplicate dependencies.");
if (keys %collated) {
diag "Potentially clashing dynamic libs detected, segfaults are possible.";
foreach my $key (sort keys %collated) {
diag "$key => " . join ' ', @{$collated{$key}};
}
}
}
}
ok (1);
}
done_testing();
Geo-GDAL-FFI-0.16/README.md 0000644 0001755 0001755 00000002573 15044551076 013604 0 ustar pause pause 





Geo-GDAL-FFI
=======================
Perl FFI to GDAL using FFI::Platypus
INSTALLATION FROM CPAN DISTRIBUTION
To build, test and install this module the basic steps are
perl Makefile.PL
make
make test
make install
DEPENDENCIES
FFI::Platypus
PDL
Alien::gdal
Alien::gdal downloads and compiles GDAL. This package will try to use
an existing GDAL in the system if Alien::gdal is not found or GDAL
location prefix is specified as an argument to Makefile.PL, for
example
perl Makefile.PL GDAL=/usr/local
DOCUMENTATION
COPYRIGHT AND LICENCE
Copyright (C) 2017- by Ari Jolma.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
Geo-GDAL-FFI-0.16/META.yml 0000644 0001755 0001755 00000001607 15201443777 013576 0 ustar pause pause ---
abstract: 'A foreign function interface to GDAL'
author:
- 'Ari Jolma '
build_requires:
Data::Dumper: '0'
ExtUtils::MakeMaker: '0'
JSON: '0'
Path::Tiny: '0'
Test::Exception: '0'
Test::More: '0'
Test::TempDir::Tiny: '0'
configure_requires:
Alien::gdal: '0'
dynamic_config: 1
generated_by: 'ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter version 2.150010'
license: artistic_2
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: '1.4'
name: Geo-GDAL-FFI
no_index:
directory:
- t
- inc
requires:
Alien::gdal: '0'
FFI::Platypus: '0'
PDL: '0'
PkgConfig: '0.23026'
Sort::Versions: '0'
perl: '5.010'
resources:
bugtracker: https://github.com/ajolma/Geo-GDAL-FFI/issues/
repository: git://github.com/ajolma/Geo-GDAL-FFI.git
version: '0.16'
x_serialization_backend: 'CPAN::Meta::YAML version 0.020'
Geo-GDAL-FFI-0.16/META.json 0000644 0001755 0001755 00000003174 15201444007 013732 0 ustar pause pause {
"abstract" : "A foreign function interface to GDAL",
"author" : [
"Ari Jolma "
],
"dynamic_config" : 1,
"generated_by" : "ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter version 2.150010",
"license" : [
"artistic_2"
],
"meta-spec" : {
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
"version" : 2
},
"name" : "Geo-GDAL-FFI",
"no_index" : {
"directory" : [
"t",
"inc"
]
},
"prereqs" : {
"build" : {
"requires" : {
"ExtUtils::MakeMaker" : "0"
}
},
"configure" : {
"requires" : {
"Alien::gdal" : "0"
}
},
"runtime" : {
"requires" : {
"Alien::gdal" : "0",
"FFI::Platypus" : "0",
"PDL" : "0",
"PkgConfig" : "0.23026",
"Sort::Versions" : "0",
"perl" : "5.010"
}
},
"test" : {
"requires" : {
"Data::Dumper" : "0",
"JSON" : "0",
"Path::Tiny" : "0",
"Test::Exception" : "0",
"Test::More" : "0",
"Test::TempDir::Tiny" : "0"
}
}
},
"release_status" : "stable",
"resources" : {
"bugtracker" : {
"web" : "https://github.com/ajolma/Geo-GDAL-FFI/issues/"
},
"repository" : {
"type" : "git",
"url" : "git://github.com/ajolma/Geo-GDAL-FFI.git",
"web" : "https://github.com/ajolma/Geo-GDAL-FFI"
}
},
"version" : "0.16",
"x_serialization_backend" : "JSON::PP version 4.16"
}
Geo-GDAL-FFI-0.16/MANIFEST.SKIP 0000644 0001755 0001755 00000000644 15044551070 014212 0 ustar pause pause ^blib
.git.+
t/.*\.html
t/src/test.exe
t/src/test.o
^Alien-gdal-
t-disabled
Makefile.old
MANIFEST.bak
Makefile$
MYMETA.yml
MYMETA.json
.+\.html
pod2htmd.tmp$
.*\.tar\.gz$
\.sr\.lock
x\.tmp
pm_to_blib
appveyor.yml
.travis.yml
.cirrus.yml
Aien-gdal.ppd
zzz.txt
^_alien
gp_changer.pl
tarballs.zip
xt/.perlcritic-history
^testalien
^.idea
.iml$
ci/
Geo-GDAL-FFI-0.16/MANIFEST 0000644 0001755 0001755 00000001347 15044551067 013454 0 ustar pause pause build-tools/parse_h.pl
build-tools/README
Changes
lib/Geo/GDAL/FFI.pm
lib/Geo/GDAL/FFI/Band.pm
lib/Geo/GDAL/FFI/Dataset.pm
lib/Geo/GDAL/FFI/Driver.pm
lib/Geo/GDAL/FFI/Feature.pm
lib/Geo/GDAL/FFI/FeatureDefn.pm
lib/Geo/GDAL/FFI/FieldDefn.pm
lib/Geo/GDAL/FFI/Geometry.pm
lib/Geo/GDAL/FFI/GeomFieldDefn.pm
lib/Geo/GDAL/FFI/Layer.pm
lib/Geo/GDAL/FFI/Object.pm
lib/Geo/GDAL/FFI/SpatialReference.pm
lib/Geo/GDAL/FFI/VSI.pm
lib/Geo/GDAL/FFI/VSI/File.pm
LICENSE
Makefile.PL
MANIFEST This list of files
MANIFEST.SKIP
META.json
META.yml
README.md
t/00-diag-aliens.t
t/01.t
t/dataset.t
t/dataset_rasterize.t
t/geometry.t
t/layer.t
t/open.t
t/pdl.t
t/schema.t
t/sr.t
t/threads.t
t/transform.t
t/vsi.t
t/vsistdout.t
Geo-GDAL-FFI-0.16/Makefile.PL 0000644 0001755 0001755 00000002415 15044551066 014271 0 ustar pause pause use strict;
use warnings;
use ExtUtils::MakeMaker 6.52;
use Config;
my %args = (
AUTHOR => ['Ari Jolma '],
NAME => 'Geo::GDAL::FFI',
ABSTRACT_FROM => "lib/Geo/GDAL/FFI.pm",
VERSION_FROM => "lib/Geo/GDAL/FFI.pm",
LICENSE => "artistic_2",
MIN_PERL_VERSION => '5.010',
CONFIGURE_REQUIRES => {
'Alien::gdal' => 0,
},
PREREQ_PM => {
'PkgConfig' => 0.23026,
'FFI::Platypus' => 0,
'PDL' => 0,
'Sort::Versions' => 0,
'Alien::gdal' => 0,
},
TEST_REQUIRES => {
'Test::More' => 0,
'Test::Exception' => 0,
'JSON' => 0,
'Data::Dumper' => 0,
'Path::Tiny' => 0,
'Test::TempDir::Tiny' => 0,
},
META_MERGE => {
"meta-spec" => { version => 2 },
resources => {
repository => {
type => 'git',
url => 'git://github.com/ajolma/Geo-GDAL-FFI.git',
web => 'https://github.com/ajolma/Geo-GDAL-FFI',
},
bugtracker => {
web => 'https://github.com/ajolma/Geo-GDAL-FFI/issues/',
},
},
},
);
WriteMakefile(%args);
Geo-GDAL-FFI-0.16/LICENSE 0000644 0001755 0001755 00000014464 15044551064 013331 0 ustar pause pause
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
Geo-GDAL-FFI-0.16/lib/ 0000755 0001755 0001755 00000000000 15201444175 013060 5 ustar pause pause Geo-GDAL-FFI-0.16/lib/Geo/ 0000755 0001755 0001755 00000000000 15201443773 013575 5 ustar pause pause Geo-GDAL-FFI-0.16/lib/Geo/GDAL/ 0000755 0001755 0001755 00000000000 15201443773 014304 5 ustar pause pause Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI.pm 0000644 0001755 0001755 00000332631 15201437455 015256 0 ustar pause pause package Geo::GDAL::FFI;
use v5.10;
use strict;
use warnings;
use Carp;
use PDL::Types ();
use Config (); # needed to silence some FFI::Platypus warnings
use FFI::Platypus;
use FFI::Platypus::Buffer;
require Exporter;
require B;
use Sort::Versions;
use Geo::GDAL::FFI::VSI;
use Geo::GDAL::FFI::VSI::File;
use Geo::GDAL::FFI::SpatialReference;
use Geo::GDAL::FFI::Object;
use Geo::GDAL::FFI::Driver;
use Geo::GDAL::FFI::Dataset;
use Geo::GDAL::FFI::Band;
use Geo::GDAL::FFI::Layer;
use Geo::GDAL::FFI::FeatureDefn;
use Geo::GDAL::FFI::FieldDefn;
use Geo::GDAL::FFI::GeomFieldDefn;
use Geo::GDAL::FFI::Feature;
use Geo::GDAL::FFI::Geometry;
our $VERSION = '0.16';
our $DEBUG = 0;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(@errors GetVersionInfo SetErrorHandling UnsetErrorHandling
Capabilities OpenFlags DataTypes ResamplingMethods
FieldTypes FieldSubtypes Justifications ColorInterpretations
GeometryTypes GeometryFormats GridAlgorithms
GetDriver GetDrivers IdentifyDriver Open
HaveGEOS SetConfigOption GetConfigOption
FindFile PushFinderLocation PopFinderLocation FinderClean);
our %EXPORT_TAGS = (all => \@EXPORT_OK);
our $None = 0;
our $Debug = 1;
our $Warning = 2;
our $Failure = 3;
our $Fatal = 4;
our %ogr_errors = (
1 => 'NOT_ENOUGH_DATA',
2 => 'NOT_ENOUGH_MEMORY',
3 => 'UNSUPPORTED_GEOMETRY_TYPE',
4 => 'UNSUPPORTED_OPERATION',
5 => 'CORRUPT_DATA',
6 => 'FAILURE',
7 => 'UNSUPPORTED_SRS',
8 => 'INVALID_HANDLE',
9 => 'NON_EXISTING_FEATURE',
);
our $Read = 0;
our $Write = 1;
our @errors;
our %immutable;
my %parent_ref_hash;
#say STDERR "XXX " . $ENV{LD_LIBRARY_PATH};
#my $instance = __PACKAGE__->new;
my $instance;
sub SetErrorHandling {
return unless $instance;
return if exists $instance->{CPLErrorHandler};
$instance->{CPLErrorHandler} = $instance->{ffi}->closure(
sub {
my ($err_cat, $err_num, $msg) = @_;
if ($err_cat == $None) {
} elsif ($err_cat == $Debug) {
if ($DEBUG) {
print STDERR $msg;
}
} elsif ($err_cat == $Warning) {
warn $msg;
} else {
push @errors, $msg;
}
});
$instance->{CPLErrorHandler}->sticky;
CPLPushErrorHandler($instance->{CPLErrorHandler});
}
sub UnsetErrorHandling {
return unless $instance;
return unless exists $instance->{CPLErrorHandler};
$instance->{CPLErrorHandler}->unstick;
CPLPopErrorHandler($instance->{CPLErrorHandler});
delete $instance->{CPLErrorHandler};
}
sub error_msg {
my $args = shift;
return unless @errors || $args;
unless (@errors) {
return $ogr_errors{$args->{OGRError}} if $args->{OGRError};
return "Unknown error.";
}
my $msg = join("\n", @errors);
@errors = ();
return $msg;
}
# internal methods
sub _register_parent_ref {
my ($gdal_handle, $parent) = @_;
# ensure $gdal_handle is not blessed?
confess "gdal handle is undefined"
if !defined $gdal_handle;
confess "Parent ref is undefined"
if !$parent;
$parent_ref_hash{$gdal_handle} = $parent;
}
sub _deregister_parent_ref {
my ($gdal_handle) = @_;
# we get undef vals in global cleanup
return if !$gdal_handle;
delete $parent_ref_hash{$gdal_handle};
}
sub _get_parent_ref {
my ($gdal_handle) = @_;
warn "Attempting to access non-existent parent"
if !$parent_ref_hash{$gdal_handle};
return $parent_ref_hash{$gdal_handle}
}
our %capabilities = (
OPEN => 1,
CREATE => 2,
CREATECOPY => 3,
VIRTUALIO => 4,
RASTER => 5,
VECTOR => 6,
GNM => 7,
NOTNULL_FIELDS => 8,
DEFAULT_FIELDS => 9,
NOTNULL_GEOMFIELDS => 10,
NONSPATIAL => 11,
FEATURE_STYLES => 12,
);
sub Capabilities {
return sort {$capabilities{$a} <=> $capabilities{$b}} keys %capabilities;
}
our %open_flags = (
READONLY => 0x00,
UPDATE => 0x01,
ALL => 0x00,
RASTER => 0x02,
VECTOR => 0x04,
GNM => 0x08,
SHARED => 0x20,
VERBOSE_ERROR => 0x40,
INTERNAL => 0x80,
ARRAY_BLOCK_ACCESS => 0x100,
HASHSET_BLOCK_ACCESS => 0x200,
);
sub OpenFlags {
return sort {$open_flags{$a} <=> $open_flags{$b}} keys %open_flags;
}
our %data_types = (
Unknown => 0,
Byte => 1,
UInt16 => 2,
Int16 => 3,
UInt32 => 4,
Int32 => 5,
Float32 => 6,
Float64 => 7,
CInt16 => 8,
CInt32 => 9,
CFloat32 => 10,
CFloat64 => 11
);
our %data_types_reverse = reverse %data_types;
sub DataTypes {
return sort {$data_types{$a} <=> $data_types{$b}} keys %data_types;
}
our %rat_field_type = (
Integer => 0,
Real => 1,
String => 2
);
our %rat_field_usage = (
Generic => 0,
PixelCount => 1,
Name => 2,
Min => 3,
Max => 4,
MinMax => 5,
Red => 6,
Green => 7,
Blue => 8,
Alpha => 9,
RedMin => 10,
GreenMin => 11,
BlueMin => 12,
AlphaMin => 13,
RedMax => 14,
GreenMax => 15,
BlueMax => 16,
AlphaMax => 17,
);
our %rat_table_type = (
THEMATIC => 0,
ATHEMATIC => 1
);
our %resampling = (
NearestNeighbour => 0,
Bilinear => 1,
Cubic => 2,
CubicSpline => 3,
ORA_Lanczos => 4,
Average => 5,
Mode => 6,
Gauss => 7
);
sub ResamplingMethods {
return sort {$resampling{$a} <=> $resampling{$b}} keys %resampling;
}
our %data_type2pdl_data_type = (
Byte => $PDL::Types::PDL_B,
Int16 => $PDL::Types::PDL_S,
UInt16 => $PDL::Types::PDL_US,
Int32 => $PDL::Types::PDL_L,
Float32 => $PDL::Types::PDL_F,
Float64 => $PDL::Types::PDL_D,
);
our %pdl_data_type2data_type = reverse %data_type2pdl_data_type;
our %field_types = (
Integer => 0,
IntegerList => 1,
Real => 2,
RealList => 3,
String => 4,
StringList => 5,
#WideString => 6, # do not use
#WideStringList => 7, # do not use
Binary => 8,
Date => 9,
Time => 10,
DateTime => 11,
Integer64 => 12,
Integer64List => 13,
);
our %field_types_reverse = reverse %field_types;
sub FieldTypes {
return sort {$field_types{$a} <=> $field_types{$b}} keys %field_types;
}
our %field_subtypes = (
None => 0,
Boolean => 1,
Int16 => 2,
Float32 => 3
);
our %field_subtypes_reverse = reverse %field_subtypes;
sub FieldSubtypes {
return sort {$field_subtypes{$a} <=> $field_subtypes{$b}} keys %field_subtypes;
}
our %justification = (
Undefined => 0,
Left => 1,
Right => 2
);
our %justification_reverse = reverse %justification;
sub Justifications {
return sort {$justification{$a} <=> $justification{$b}} keys %justification;
}
our %color_interpretations = (
Undefined => 0,
GrayIndex => 1,
PaletteIndex => 2,
RedBand => 3,
GreenBand => 4,
BlueBand => 5,
AlphaBand => 6,
HueBand => 7,
SaturationBand => 8,
LightnessBand => 9,
CyanBand => 10,
MagentaBand => 11,
YellowBand => 12,
BlackBand => 13,
YCbCr_YBand => 14,
YCbCr_CbBand => 15,
YCbCr_CrBand => 16,
);
our %color_interpretations_reverse = reverse %color_interpretations;
sub ColorInterpretations {
return sort {$color_interpretations{$a} <=> $color_interpretations{$b}} keys %color_interpretations;
}
our %geometry_types = (
Unknown => 0,
Point => 1,
LineString => 2,
Polygon => 3,
MultiPoint => 4,
MultiLineString => 5,
MultiPolygon => 6,
GeometryCollection => 7,
CircularString => 8,
CompoundCurve => 9,
CurvePolygon => 10,
MultiCurve => 11,
MultiSurface => 12,
Curve => 13,
Surface => 14,
PolyhedralSurface => 15,
TIN => 16,
Triangle => 17,
None => 100,
LinearRing => 101,
CircularStringZ => 1008,
CompoundCurveZ => 1009,
CurvePolygonZ => 1010,
MultiCurveZ => 1011,
MultiSurfaceZ => 1012,
CurveZ => 1013,
SurfaceZ => 1014,
PolyhedralSurfaceZ => 1015,
TINZ => 1016,
TriangleZ => 1017,
PointM => 2001,
LineStringM => 2002,
PolygonM => 2003,
MultiPointM => 2004,
MultiLineStringM => 2005,
MultiPolygonM => 2006,
GeometryCollectionM => 2007,
CircularStringM => 2008,
CompoundCurveM => 2009,
CurvePolygonM => 2010,
MultiCurveM => 2011,
MultiSurfaceM => 2012,
CurveM => 2013,
SurfaceM => 2014,
PolyhedralSurfaceM => 2015,
TINM => 2016,
TriangleM => 2017,
PointZM => 3001,
LineStringZM => 3002,
PolygonZM => 3003,
MultiPointZM => 3004,
MultiLineStringZM => 3005,
MultiPolygonZM => 3006,
GeometryCollectionZM => 3007,
CircularStringZM => 3008,
CompoundCurveZM => 3009,
CurvePolygonZM => 3010,
MultiCurveZM => 3011,
MultiSurfaceZM => 3012,
CurveZM => 3013,
SurfaceZM => 3014,
PolyhedralSurfaceZM => 3015,
TINZM => 3016,
TriangleZM => 3017,
Point25D => 0x80000001,
LineString25D => 0x80000002,
Polygon25D => 0x80000003,
MultiPoint25D => 0x80000004,
MultiLineString25D => 0x80000005,
MultiPolygon25D => 0x80000006,
GeometryCollection25D => 0x80000007
);
our %geometry_types_reverse = reverse %geometry_types;
sub GeometryTypes {
return sort {$geometry_types{$a} <=> $geometry_types{$b}} keys %geometry_types;
}
our %geometry_formats = (
WKT => 1,
);
sub GeometryFormats {
return sort {$geometry_formats{$a} <=> $geometry_formats{$b}} keys %geometry_formats;
}
our %grid_algorithms = (
InverseDistanceToAPower => 1,
MovingAverage => 2,
NearestNeighbor => 3,
MetricMinimum => 4,
MetricMaximum => 5,
MetricRange => 6,
MetricCount => 7,
MetricAverageDistance => 8,
MetricAverageDistancePts => 9,
Linear => 10,
InverseDistanceToAPowerNearestNeighbor => 11
);
sub GridAlgorithms {
return sort {$grid_algorithms{$a} <=> $grid_algorithms{$b}} keys %grid_algorithms;
}
sub isint {
my $value = shift;
my $b_obj = B::svref_2object(\$value);
my $flags = $b_obj->FLAGS;
return 1 if $flags & B::SVp_IOK() && !($flags & B::SVp_NOK()) && !($flags & B::SVp_POK());
}
sub new {
my $class = shift;
my $gdal = shift;
return $instance if $instance;
my $ffi = FFI::Platypus->new;
my @libs = $gdal->dynamic_libs;
$ffi->lib(@libs);
$ffi->type('(pointer,size_t,size_t,opaque)->size_t' => 'VSIWriteFunction');
$ffi->type('(int,int,string)->void' => 'CPLErrorHandler');
$ffi->type('(double,string,pointer)->int' => 'GDALProgressFunc');
$ffi->type('(pointer,int, pointer,int,int,unsigned int,unsigned int,int,int)->int' => 'GDALDerivedPixelFunc');
$ffi->type('(pointer,int,int,pointer,pointer,pointer,pointer)->int' => 'GDALTransformerFunc');
$ffi->type('(double,int,pointer,pointer,pointer)->int' => 'GDALContourWriter');
$ffi->type('(string,string,sint64,sint64,pointer)->void' => 'GDALQueryLoggerFunc');
$ffi->type('(string,pointer,pointer,int,int,pointer,pointer,pointer,pointer,pointer,pointer)->int' => 'GDALVRTProcessedDatasetFuncInit');
$ffi->type('(string,pointer,pointer)->void' => 'GDALVRTProcessedDatasetFuncFree');
$ffi->type('(string,pointer,pointer,int,int,int,pointer,size_t,int,int,pointer,pointer,size_t,int,int,pointer,double,double,double,double,pointer,string,int)->int' => 'GDALVRTProcessedDatasetFuncProcess');
$ffi->ignore_not_found(1);
# from port/*.h
$ffi->attach(VSIMalloc => [qw/uint/] => 'opaque');
croak "Can't attach to GDAL methods. Problem with GDAL dynamic libs: '@libs'?" unless $class->can('VSIMalloc');
$ffi->attach(VSIFree => ['opaque'] => 'void');
$ffi->attach(CPLError => [qw/int int string/] => 'void');
$ffi->attach(VSIFOpenL => [qw/string string/] => 'opaque');
$ffi->attach(VSIFOpenExL => [qw/string string int/] => 'opaque');
$ffi->attach(VSIFCloseL => ['opaque'] => 'int');
$ffi->attach(VSIFWriteL => [qw/opaque uint uint opaque/] => 'uint');
$ffi->attach(VSIFReadL => [qw/opaque uint uint opaque/] => 'uint');
$ffi->attach(VSIIngestFile => [qw/opaque string string* uint64* sint64/] => 'int');
$ffi->attach(VSIMkdir => [qw/string sint64/] => 'int');
$ffi->attach(VSIRmdir => [qw/string/] => 'int');
$ffi->attach(VSIReadDirEx => [qw/string int/] => 'opaque');
$ffi->attach(VSIUnlink => [qw/string/] => 'int');
$ffi->attach(VSIRename => [qw/string string/] => 'int');
$ffi->attach(VSIStdoutSetRedirection => ['VSIWriteFunction', 'opaque'] => 'void');
$ffi->attach(CPLSetErrorHandler => ['CPLErrorHandler'] => 'opaque');
$ffi->attach(CPLPushErrorHandler => ['CPLErrorHandler'] => 'void');
$ffi->attach(CPLPopErrorHandler => ['CPLErrorHandler'] => 'void');
$ffi->attach(CSLDestroy => ['opaque'] => 'void');
$ffi->attach(CSLAddString => ['opaque', 'string'] => 'opaque');
$ffi->attach(CSLCount => ['opaque'] => 'int');
$ffi->attach(CSLGetField => ['opaque', 'int'] => 'string');
$ffi->attach(CPLGetConfigOption => ['string', 'string'] => 'string');
$ffi->attach(CPLSetConfigOption => ['string', 'string'] => 'void');
$ffi->attach(CPLFindFile => ['string', 'string'] => 'string');
$ffi->attach(CPLPushFinderLocation => ['string'] => 'void');
$ffi->attach(CPLPopFinderLocation => [] => 'void');
$ffi->attach(CPLFinderClean => [] => 'void');
# from ogr_core.h
$ffi->attach( 'OGR_GT_Flatten' => ['unsigned int'] => 'unsigned int');
# generated with parse_h.pl
# from gcore/gdal.h
$ffi->attach('GDALGetDataTypeSize' => ['unsigned int'] => 'int');
$ffi->attach('GDALGetDataTypeSizeBits' => ['unsigned int'] => 'int');
$ffi->attach('GDALGetDataTypeSizeBytes' => ['unsigned int'] => 'int');
$ffi->attach('GDALDataTypeIsComplex' => ['unsigned int'] => 'int');
$ffi->attach('GDALDataTypeIsInteger' => ['unsigned int'] => 'int');
$ffi->attach('GDALDataTypeIsFloating' => ['unsigned int'] => 'int');
$ffi->attach('GDALDataTypeIsSigned' => ['unsigned int'] => 'int');
$ffi->attach('GDALGetDataTypeName' => ['unsigned int'] => 'string');
$ffi->attach('GDALGetDataTypeByName' => [qw/string/] => 'unsigned int');
$ffi->attach('GDALDataTypeUnion' => ['unsigned int','unsigned int'] => 'unsigned int');
$ffi->attach('GDALDataTypeUnionWithValue' => ['unsigned int','double','int'] => 'unsigned int');
$ffi->attach('GDALFindDataType' => [qw/int int int int/] => 'unsigned int');
$ffi->attach('GDALFindDataTypeForValue' => [qw/double int/] => 'unsigned int');
$ffi->attach('GDALAdjustValueToDataType' => ['unsigned int','double','int*','int*'] => 'double');
$ffi->attach('GDALGetNonComplexDataType' => ['unsigned int'] => 'unsigned int');
$ffi->attach('GDALDataTypeIsConversionLossy' => ['unsigned int','unsigned int'] => 'int');
$ffi->attach('GDALGetAsyncStatusTypeName' => ['unsigned int'] => 'string');
$ffi->attach('GDALGetAsyncStatusTypeByName' => [qw/string/] => 'unsigned int');
$ffi->attach('GDALGetColorInterpretationName' => ['unsigned int'] => 'string');
$ffi->attach('GDALGetColorInterpretationByName' => [qw/string/] => 'unsigned int');
$ffi->attach('GDALGetPaletteInterpretationName' => ['unsigned int'] => 'string');
$ffi->attach('GDALAllRegister' => [] => 'void');
$ffi->attach('GDALCreate' => ['opaque','string','int','int','int','unsigned int','opaque'] => 'opaque');
$ffi->attach('GDALCreateCopy' => [qw/opaque string opaque int opaque GDALProgressFunc opaque/] => 'opaque');
$ffi->attach('GDALIdentifyDriver' => [qw/string opaque/] => 'opaque');
$ffi->attach('GDALIdentifyDriverEx' => ['string','unsigned int','opaque','opaque'] => 'opaque');
$ffi->attach('GDALOpen' => ['string','unsigned int'] => 'opaque');
$ffi->attach('GDALOpenShared' => ['string','unsigned int'] => 'opaque');
$ffi->attach('GDALOpenEx' => ['string','unsigned int','opaque','opaque','opaque'] => 'opaque');
$ffi->attach('GDALDumpOpenDatasets' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetDriverByName' => [qw/string/] => 'opaque');
$ffi->attach('GDALGetDriverCount' => [] => 'int');
$ffi->attach('GDALGetDriver' => [qw/int/] => 'opaque');
$ffi->attach('GDALCreateDriver' => [] => 'opaque');
$ffi->attach('GDALDestroyDriver' => [qw/opaque/] => 'void');
$ffi->attach('GDALRegisterDriver' => [qw/opaque/] => 'int');
$ffi->attach('GDALDeregisterDriver' => [qw/opaque/] => 'void');
$ffi->attach('GDALDestroyDriverManager' => [] => 'void');
$ffi->attach('GDALDestroy' => [] => 'void');
$ffi->attach('GDALDeleteDataset' => [qw/opaque string/] => 'int');
$ffi->attach('GDALRenameDataset' => [qw/opaque string string/] => 'int');
$ffi->attach('GDALCopyDatasetFiles' => [qw/opaque string string/] => 'int');
$ffi->attach('GDALValidateCreationOptions' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALGetDriverShortName' => [qw/opaque/] => 'string');
$ffi->attach('GDALGetDriverLongName' => [qw/opaque/] => 'string');
$ffi->attach('GDALGetDriverHelpTopic' => [qw/opaque/] => 'string');
$ffi->attach('GDALGetDriverCreationOptionList' => [qw/opaque/] => 'string');
$ffi->attach('GDALInitGCPs' => [qw/int opaque/] => 'void');
$ffi->attach('GDALDeinitGCPs' => [qw/int opaque/] => 'void');
$ffi->attach('GDALDuplicateGCPs' => [qw/int opaque/] => 'opaque');
$ffi->attach('GDALGCPsToGeoTransform' => [qw/int opaque double* int/] => 'int');
$ffi->attach('GDALInvGeoTransform' => [qw/double[] double[]/] => 'int');
$ffi->attach('GDALApplyGeoTransform' => [qw/double[6] double double double* double*/] => 'void');
$ffi->attach('GDALComposeGeoTransforms' => [qw/double[6] double[6] double[6]/] => 'void');
$ffi->attach('GDALGetMetadataDomainList' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetMetadata' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALSetMetadata' => [qw/opaque opaque string/] => 'int');
$ffi->attach('GDALGetMetadataItem' => [qw/opaque string string/] => 'string');
$ffi->attach('GDALSetMetadataItem' => [qw/opaque string string string/] => 'int');
$ffi->attach('GDALGetDescription' => [qw/opaque/] => 'string');
$ffi->attach('GDALSetDescription' => [qw/opaque string/] => 'void');
$ffi->attach('GDALGetDatasetDriver' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetFileList' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALClose' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterXSize' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterYSize' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterBand' => [qw/opaque int/] => 'opaque');
$ffi->attach('GDALAddBand' => ['opaque','unsigned int','opaque'] => 'int');
$ffi->attach('GDALBeginAsyncReader' => ['opaque','int','int','int','int','opaque','int','int','unsigned int','int','int*','int','int','int','opaque'] => 'opaque');
$ffi->attach('GDALEndAsyncReader' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALDatasetRasterIO' => ['opaque','unsigned int','int','int','int','int','opaque','int','int','unsigned int','int','int*','int','int','int'] => 'int');
$ffi->attach('GDALDatasetRasterIOEx' => ['opaque','unsigned int','int','int','int','int','opaque','int','int','unsigned int','int','int*','sint64','sint64','sint64','opaque'] => 'int');
$ffi->attach('GDALDatasetAdviseRead' => ['opaque','int','int','int','int','int','int','unsigned int','int','int*','opaque'] => 'int');
$ffi->attach('GDALDatasetGetCompressionFormats' => [qw/opaque int int int int int int*/] => 'opaque');
$ffi->attach('GDALDatasetReadCompressedData' => [qw/opaque string int int int int int int* opaque size_t string*/] => 'int');
$ffi->attach('GDALGetProjectionRef' => [qw/opaque/] => 'string');
$ffi->attach('GDALGetSpatialRef' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALSetProjection' => [qw/opaque string/] => 'int');
$ffi->attach('GDALSetSpatialRef' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALGetGeoTransform' => [qw/opaque double[6]/] => 'int');
$ffi->attach('GDALSetGeoTransform' => [qw/opaque double[6]/] => 'int');
$ffi->attach('GDALGetGCPCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetGCPProjection' => [qw/opaque/] => 'string');
$ffi->attach('GDALGetGCPSpatialRef' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetGCPs' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALSetGCPs' => [qw/opaque int opaque string/] => 'int');
$ffi->attach('GDALSetGCPs2' => [qw/opaque int opaque opaque/] => 'int');
$ffi->attach('GDALGetInternalHandle' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALReferenceDataset' => [qw/opaque/] => 'int');
$ffi->attach('GDALDereferenceDataset' => [qw/opaque/] => 'int');
$ffi->attach('GDALReleaseDataset' => [qw/opaque/] => 'int');
$ffi->attach('GDALBuildOverviews' => [qw/opaque string int int* int int* GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALBuildOverviewsEx' => [qw/opaque string int int* int int* GDALProgressFunc opaque opaque/] => 'int');
$ffi->attach('GDALGetOpenDatasets' => [qw/uint64* int*/] => 'void');
$ffi->attach('GDALGetAccess' => [qw/opaque/] => 'int');
$ffi->attach('GDALFlushCache' => [qw/opaque/] => 'int');
$ffi->attach('GDALCreateDatasetMaskBand' => [qw/opaque int/] => 'int');
$ffi->attach('GDALDatasetCopyWholeRaster' => [qw/opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALRasterBandCopyWholeRaster' => [qw/opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALRegenerateOverviews' => [qw/opaque int uint64* string GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALRegenerateOverviewsEx' => [qw/opaque int uint64* string GDALProgressFunc opaque opaque/] => 'int');
$ffi->attach('GDALDatasetGetLayerCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALDatasetGetLayer' => [qw/opaque int/] => 'opaque');
$ffi->attach('GDALDatasetGetLayerByName' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALDatasetIsLayerPrivate' => [qw/opaque int/] => 'int');
$ffi->attach('GDALDatasetDeleteLayer' => [qw/opaque int/] => 'int');
$ffi->attach('GDALDatasetCreateLayer' => ['opaque','string','opaque','unsigned int','opaque'] => 'opaque');
$ffi->attach('GDALDatasetCopyLayer' => [qw/opaque opaque string opaque/] => 'opaque');
$ffi->attach('GDALDatasetResetReading' => [qw/opaque/] => 'void');
$ffi->attach('GDALDatasetGetNextFeature' => [qw/opaque uint64* double* GDALProgressFunc opaque/] => 'opaque');
$ffi->attach('GDALDatasetTestCapability' => [qw/opaque string/] => 'int');
$ffi->attach('GDALDatasetExecuteSQL' => [qw/opaque string opaque string/] => 'opaque');
$ffi->attach('GDALDatasetAbortSQL' => [qw/opaque/] => 'int');
$ffi->attach('GDALDatasetReleaseResultSet' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALDatasetGetStyleTable' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALDatasetSetStyleTableDirectly' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALDatasetSetStyleTable' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALDatasetStartTransaction' => [qw/opaque int/] => 'int');
$ffi->attach('GDALDatasetCommitTransaction' => [qw/opaque/] => 'int');
$ffi->attach('GDALDatasetRollbackTransaction' => [qw/opaque/] => 'int');
$ffi->attach('GDALDatasetClearStatistics' => [qw/opaque/] => 'void');
$ffi->attach('GDALDatasetGetFieldDomainNames' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALDatasetGetFieldDomain' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALDatasetAddFieldDomain' => [qw/opaque opaque string*/] => 'bool');
$ffi->attach('GDALDatasetDeleteFieldDomain' => [qw/opaque string string*/] => 'bool');
$ffi->attach('GDALDatasetUpdateFieldDomain' => [qw/opaque opaque string*/] => 'bool');
$ffi->attach('GDALDatasetGetRelationshipNames' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALDatasetGetRelationship' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALDatasetAddRelationship' => [qw/opaque opaque string*/] => 'bool');
$ffi->attach('GDALDatasetDeleteRelationship' => [qw/opaque string string*/] => 'bool');
$ffi->attach('GDALDatasetUpdateRelationship' => [qw/opaque opaque string*/] => 'bool');
$ffi->attach('GDALDatasetSetQueryLoggerFunc' => [qw/opaque GDALQueryLoggerFunc opaque/] => 'bool');
$ffi->attach('GDALGetRasterDataType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALGetBlockSize' => [qw/opaque int* int*/] => 'void');
$ffi->attach('GDALGetActualBlockSize' => [qw/opaque int int int* int*/] => 'int');
$ffi->attach('GDALRasterAdviseRead' => ['opaque','int','int','int','int','int','int','unsigned int','opaque'] => 'int');
$ffi->attach('GDALRasterIO' => ['opaque','unsigned int','int','int','int','int','opaque','int','int','unsigned int','int','int'] => 'int');
$ffi->attach('GDALRasterIOEx' => ['opaque','unsigned int','int','int','int','int','opaque','int','int','unsigned int','sint64','sint64','opaque'] => 'int');
$ffi->attach('GDALReadBlock' => [qw/opaque int int opaque/] => 'int');
$ffi->attach('GDALWriteBlock' => [qw/opaque int int opaque/] => 'int');
$ffi->attach('GDALGetRasterBandXSize' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterBandYSize' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterAccess' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALGetBandNumber' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetBandDataset' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetRasterColorInterpretation' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALSetRasterColorInterpretation' => ['opaque','unsigned int'] => 'int');
$ffi->attach('GDALGetRasterColorTable' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALSetRasterColorTable' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALHasArbitraryOverviews' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetOverviewCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetOverview' => [qw/opaque int/] => 'opaque');
$ffi->attach('GDALGetRasterNoDataValue' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALGetRasterNoDataValueAsInt64' => [qw/opaque int*/] => 'int');
$ffi->attach('GDALGetRasterNoDataValueAsUInt64' => [qw/opaque int*/] => 'uint64');
$ffi->attach('GDALSetRasterNoDataValue' => [qw/opaque double/] => 'int');
$ffi->attach('GDALSetRasterNoDataValueAsInt64' => [qw/opaque int/] => 'int');
$ffi->attach('GDALSetRasterNoDataValueAsUInt64' => [qw/opaque uint64/] => 'int');
$ffi->attach('GDALDeleteRasterNoDataValue' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterCategoryNames' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALSetRasterCategoryNames' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALGetRasterMinimum' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALGetRasterMaximum' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALGetRasterStatistics' => [qw/opaque int int double* double* double* double*/] => 'int');
$ffi->attach('GDALComputeRasterStatistics' => [qw/opaque int double* double* double* double* GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALSetRasterStatistics' => [qw/opaque double double double double/] => 'int');
$ffi->attach('GDALRasterBandAsMDArray' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetRasterUnitType' => [qw/opaque/] => 'string');
$ffi->attach('GDALSetRasterUnitType' => [qw/opaque string/] => 'int');
$ffi->attach('GDALGetRasterOffset' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALSetRasterOffset' => [qw/opaque double/] => 'int');
$ffi->attach('GDALGetRasterScale' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALSetRasterScale' => [qw/opaque double/] => 'int');
$ffi->attach('GDALComputeRasterMinMax' => [qw/opaque int double/] => 'int');
$ffi->attach('GDALFlushRasterCache' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetRasterHistogram' => [qw/opaque double double int int* int int GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALGetRasterHistogramEx' => [qw/opaque double double int uint64* int int GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALGetDefaultHistogram' => [qw/opaque double* double* int* int* int GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALGetDefaultHistogramEx' => [qw/opaque double* double* int* uint64* int GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALSetDefaultHistogram' => [qw/opaque double double int int*/] => 'int');
$ffi->attach('GDALSetDefaultHistogramEx' => [qw/opaque double double int uint64*/] => 'int');
$ffi->attach('GDALGetRandomRasterSample' => [qw/opaque int float*/] => 'int');
$ffi->attach('GDALGetRasterSampleOverview' => [qw/opaque int/] => 'opaque');
$ffi->attach('GDALGetRasterSampleOverviewEx' => [qw/opaque uint64/] => 'opaque');
$ffi->attach('GDALFillRaster' => [qw/opaque double double/] => 'int');
$ffi->attach('GDALComputeBandStats' => [qw/opaque int double* double* GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALOverviewMagnitudeCorrection' => [qw/opaque int uint64* GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALGetDefaultRAT' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALSetDefaultRAT' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALAddDerivedBandPixelFunc' => [qw/string GDALDerivedPixelFunc/] => 'int');
$ffi->attach('GDALAddDerivedBandPixelFuncWithArgs' => [qw/string GDALDerivedPixelFunc string/] => 'int');
$ffi->attach('GDALGetMaskBand' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetMaskFlags' => [qw/opaque/] => 'int');
$ffi->attach('GDALCreateMaskBand' => [qw/opaque int/] => 'int');
$ffi->attach('GDALIsMaskBand' => [qw/opaque/] => 'bool');
$ffi->attach('GDALGetDataCoverageStatus' => [qw/opaque int int int int int double*/] => 'int');
$ffi->attach('GDALARGetNextUpdatedRegion' => [qw/opaque double int* int* int* int*/] => 'unsigned int');
$ffi->attach('GDALARLockBuffer' => [qw/opaque double/] => 'int');
$ffi->attach('GDALARUnlockBuffer' => [qw/opaque/] => 'void');
$ffi->attach('GDALGeneralCmdLineProcessor' => [qw/int string* int/] => 'int');
$ffi->attach('GDALSwapWords' => [qw/opaque int int int/] => 'void');
$ffi->attach('GDALSwapWordsEx' => [qw/opaque int size_t int/] => 'void');
$ffi->attach('GDALCopyWords' => ['opaque','unsigned int','int','opaque','unsigned int','int','int'] => 'void');
$ffi->attach('GDALCopyWords64' => ['opaque','unsigned int','int','opaque','unsigned int','int','int'] => 'void');
$ffi->attach('GDALCopyBits' => [qw/pointer int int pointer int int int int/] => 'void');
$ffi->attach('GDALDeinterleave' => ['opaque','unsigned int','int','opaque','unsigned int','size_t'] => 'void');
$ffi->attach('GDALLoadWorldFile' => [qw/string double*/] => 'int');
$ffi->attach('GDALReadWorldFile' => [qw/string string double*/] => 'int');
$ffi->attach('GDALWriteWorldFile' => [qw/string string double*/] => 'int');
$ffi->attach('GDALLoadTabFile' => [qw/string double* string* int* opaque/] => 'int');
$ffi->attach('GDALReadTabFile' => [qw/string double* string* int* opaque/] => 'int');
$ffi->attach('GDALLoadOziMapFile' => [qw/string double* string* int* opaque/] => 'int');
$ffi->attach('GDALReadOziMapFile' => [qw/string double* string* int* opaque/] => 'int');
$ffi->attach('GDALDecToDMS' => [qw/double string int/] => 'string');
$ffi->attach('GDALPackedDMSToDec' => [qw/double/] => 'double');
$ffi->attach('GDALDecToPackedDMS' => [qw/double/] => 'double');
$ffi->attach('GDALVersionInfo' => [qw/string/] => 'string');
$ffi->attach('GDALCheckVersion' => [qw/int int string/] => 'int');
$ffi->attach('GDALExtractRPCInfoV1' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALExtractRPCInfoV2' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALCreateColorTable' => ['unsigned int'] => 'opaque');
$ffi->attach('GDALDestroyColorTable' => [qw/opaque/] => 'void');
$ffi->attach('GDALCloneColorTable' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGetPaletteInterpretation' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALGetColorEntryCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALGetColorEntry' => [qw/opaque int/] => 'short[4]');
$ffi->attach('GDALGetColorEntryAsRGB' => [qw/opaque int short[4]/] => 'int');
$ffi->attach('GDALSetColorEntry' => [qw/opaque int short[4]/] => 'void');
$ffi->attach('GDALCreateColorRamp' => [qw/opaque int short[4] int short[4]/] => 'void');
$ffi->attach('GDALCreateRasterAttributeTable' => [] => 'opaque');
$ffi->attach('GDALDestroyRasterAttributeTable' => [qw/opaque/] => 'void');
$ffi->attach('GDALRATGetColumnCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALRATGetNameOfCol' => [qw/opaque int/] => 'string');
$ffi->attach('GDALRATGetUsageOfCol' => [qw/opaque int/] => 'unsigned int');
$ffi->attach('GDALRATGetTypeOfCol' => [qw/opaque int/] => 'unsigned int');
$ffi->attach('GDALRATGetColOfUsage' => ['opaque','unsigned int'] => 'int');
$ffi->attach('GDALRATGetRowCount' => [qw/opaque/] => 'int');
$ffi->attach('GDALRATGetValueAsString' => [qw/opaque int int/] => 'string');
$ffi->attach('GDALRATGetValueAsInt' => [qw/opaque int int/] => 'int');
$ffi->attach('GDALRATGetValueAsDouble' => [qw/opaque int int/] => 'double');
$ffi->attach('GDALRATSetValueAsString' => [qw/opaque int int string/] => 'void');
$ffi->attach('GDALRATSetValueAsInt' => [qw/opaque int int int/] => 'void');
$ffi->attach('GDALRATSetValueAsDouble' => [qw/opaque int int double/] => 'void');
$ffi->attach('GDALRATChangesAreWrittenToFile' => [qw/opaque/] => 'int');
$ffi->attach('GDALRATValuesIOAsDouble' => ['opaque','unsigned int','int','int','int','double*'] => 'int');
$ffi->attach('GDALRATValuesIOAsInteger' => ['opaque','unsigned int','int','int','int','int*'] => 'int');
$ffi->attach('GDALRATValuesIOAsString' => ['opaque','unsigned int','int','int','int','opaque'] => 'int');
$ffi->attach('GDALRATSetRowCount' => [qw/opaque int/] => 'void');
$ffi->attach('GDALRATCreateColumn' => ['opaque','string','unsigned int','unsigned int'] => 'int');
$ffi->attach('GDALRATSetLinearBinning' => [qw/opaque double double/] => 'int');
$ffi->attach('GDALRATGetLinearBinning' => [qw/opaque double* double*/] => 'int');
$ffi->attach('GDALRATSetTableType' => ['opaque','unsigned int'] => 'int');
$ffi->attach('GDALRATGetTableType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALRATInitializeFromColorTable' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALRATTranslateToColorTable' => [qw/opaque int/] => 'opaque');
$ffi->attach('GDALRATDumpReadable' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALRATClone' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALRATSerializeJSON' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALRATGetRowOfValue' => [qw/opaque double/] => 'int');
$ffi->attach('GDALRATRemoveStatistics' => [qw/opaque/] => 'void');
$ffi->attach('GDALRelationshipCreate' => ['string','string','string','unsigned int'] => 'opaque');
$ffi->attach('GDALDestroyRelationship' => [qw/opaque/] => 'void');
$ffi->attach('GDALRelationshipGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipGetCardinality' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALRelationshipGetLeftTableName' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipGetRightTableName' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipGetMappingTableName' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipSetMappingTableName' => [qw/opaque string/] => 'void');
$ffi->attach('GDALRelationshipGetLeftTableFields' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALRelationshipGetRightTableFields' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALRelationshipSetLeftTableFields' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALRelationshipSetRightTableFields' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALRelationshipGetLeftMappingTableFields' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALRelationshipGetRightMappingTableFields' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALRelationshipSetLeftMappingTableFields' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALRelationshipSetRightMappingTableFields' => [qw/opaque opaque/] => 'void');
$ffi->attach('GDALRelationshipGetType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALRelationshipSetType' => ['opaque','unsigned int'] => 'void');
$ffi->attach('GDALRelationshipGetForwardPathLabel' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipSetForwardPathLabel' => [qw/opaque string/] => 'void');
$ffi->attach('GDALRelationshipGetBackwardPathLabel' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipSetBackwardPathLabel' => [qw/opaque string/] => 'void');
$ffi->attach('GDALRelationshipGetRelatedTableType' => [qw/opaque/] => 'string');
$ffi->attach('GDALRelationshipSetRelatedTableType' => [qw/opaque string/] => 'void');
$ffi->attach('GDALSetCacheMax' => [qw/int/] => 'void');
$ffi->attach('GDALGetCacheMax' => [] => 'int');
$ffi->attach('GDALGetCacheUsed' => [] => 'int');
$ffi->attach('GDALSetCacheMax64' => [qw/sint64/] => 'void');
$ffi->attach('GDALGetCacheMax64' => [] => 'sint64');
$ffi->attach('GDALGetCacheUsed64' => [] => 'sint64');
$ffi->attach('GDALFlushCacheBlock' => [] => 'int');
$ffi->attach('GDALDatasetGetVirtualMem' => ['opaque','unsigned int','int','int','int','int','int','int','unsigned int','int','int*','int','sint64','sint64','size_t','size_t','int','opaque'] => 'opaque');
$ffi->attach('GDALRasterBandGetVirtualMem' => ['opaque','unsigned int','int','int','int','int','int','int','unsigned int','int','sint64','size_t','size_t','int','opaque'] => 'opaque');
$ffi->attach('GDALGetVirtualMemAuto' => ['opaque','unsigned int','int*','sint64*','opaque'] => 'opaque');
$ffi->attach('GDALDatasetGetTiledVirtualMem' => ['opaque','unsigned int','int','int','int','int','int','int','unsigned int','int','int*','unsigned int','size_t','int','opaque'] => 'opaque');
$ffi->attach('GDALRasterBandGetTiledVirtualMem' => ['opaque','unsigned int','int','int','int','int','int','int','unsigned int','size_t','int','opaque'] => 'opaque');
$ffi->attach('GDALCreatePansharpenedVRT' => [qw/string opaque int uint64*/] => 'opaque');
$ffi->attach('GDALGetJPEG2000Structure' => [qw/string opaque/] => 'opaque');
$ffi->attach('GDALCreateMultiDimensional' => [qw/opaque string opaque opaque/] => 'opaque');
$ffi->attach('GDALExtendedDataTypeCreate' => ['unsigned int'] => 'opaque');
$ffi->attach('GDALExtendedDataTypeCreateString' => [qw/size_t/] => 'opaque');
$ffi->attach('GDALExtendedDataTypeCreateStringEx' => [qw/size_t int/] => 'opaque');
$ffi->attach('GDALExtendedDataTypeCreateCompound' => [qw/string size_t size_t opaque/] => 'opaque');
$ffi->attach('GDALExtendedDataTypeRelease' => [qw/opaque/] => 'void');
$ffi->attach('GDALExtendedDataTypeGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALExtendedDataTypeGetClass' => [qw/opaque/] => 'int');
$ffi->attach('GDALExtendedDataTypeGetNumericDataType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('GDALExtendedDataTypeGetSize' => [qw/opaque/] => 'size_t');
$ffi->attach('GDALExtendedDataTypeGetMaxStringLength' => [qw/opaque/] => 'size_t');
$ffi->attach('GDALExtendedDataTypeGetComponents' => [qw/opaque size_t/] => 'uint64*');
$ffi->attach('GDALExtendedDataTypeFreeComponents' => [qw/uint64* size_t/] => 'void');
$ffi->attach('GDALExtendedDataTypeCanConvertTo' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALExtendedDataTypeEquals' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALExtendedDataTypeGetSubType' => [qw/opaque/] => 'int');
$ffi->attach('GDALEDTComponentCreate' => [qw/string size_t opaque/] => 'opaque');
$ffi->attach('GDALEDTComponentRelease' => [qw/opaque/] => 'void');
$ffi->attach('GDALEDTComponentGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALEDTComponentGetOffset' => [qw/opaque/] => 'size_t');
$ffi->attach('GDALEDTComponentGetType' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALDatasetGetRootGroup' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGroupRelease' => [qw/opaque/] => 'void');
$ffi->attach('GDALGroupGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALGroupGetFullName' => [qw/opaque/] => 'string');
$ffi->attach('GDALGroupGetMDArrayNames' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALGroupOpenMDArray' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('GDALGroupOpenMDArrayFromFullname' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('GDALGroupResolveMDArray' => [qw/opaque string string opaque/] => 'opaque');
$ffi->attach('GDALGroupGetGroupNames' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALGroupOpenGroup' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('GDALGroupOpenGroupFromFullname' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('GDALGroupGetVectorLayerNames' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALGroupOpenVectorLayer' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('GDALGroupGetDimensions' => [qw/opaque size_t opaque/] => 'uint64*');
$ffi->attach('GDALGroupGetAttribute' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALGroupGetAttributes' => [qw/opaque size_t opaque/] => 'uint64*');
$ffi->attach('GDALGroupGetStructuralInfo' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALGroupCreateGroup' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('GDALGroupCreateDimension' => [qw/opaque string string string uint64 opaque/] => 'opaque');
$ffi->attach('GDALGroupCreateMDArray' => [qw/opaque string size_t uint64* opaque opaque/] => 'opaque');
$ffi->attach('GDALGroupCreateAttribute' => [qw/opaque string size_t uint64* opaque opaque/] => 'opaque');
$ffi->attach('GDALMDArrayRelease' => [qw/opaque/] => 'void');
$ffi->attach('GDALMDArrayGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALMDArrayGetFullName' => [qw/opaque/] => 'string');
$ffi->attach('GDALMDArrayGetTotalElementsCount' => [qw/opaque/] => 'uint64');
$ffi->attach('GDALMDArrayGetDimensionCount' => [qw/opaque/] => 'size_t');
$ffi->attach('GDALMDArrayGetDimensions' => [qw/opaque size_t/] => 'uint64*');
$ffi->attach('GDALMDArrayGetDataType' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALMDArrayRead' => [qw/opaque uint64* size_t sint64 int* opaque opaque opaque size_t/] => 'int');
$ffi->attach('GDALMDArrayWrite' => [qw/opaque uint64* size_t sint64 int* opaque opaque opaque size_t/] => 'int');
$ffi->attach('GDALMDArrayAdviseRead' => [qw/opaque uint64* size_t/] => 'int');
$ffi->attach('GDALMDArrayAdviseReadEx' => [qw/opaque uint64* size_t opaque/] => 'int');
$ffi->attach('GDALMDArrayGetAttribute' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALMDArrayGetAttributes' => [qw/opaque size_t opaque/] => 'uint64*');
$ffi->attach('GDALMDArrayCreateAttribute' => [qw/opaque string size_t uint64* opaque opaque/] => 'opaque');
$ffi->attach('GDALMDArrayResize' => [qw/opaque uint64* opaque/] => 'bool');
$ffi->attach('GDALMDArrayGetRawNoDataValue' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALMDArrayGetNoDataValueAsDouble' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALMDArrayGetNoDataValueAsInt64' => [qw/opaque int*/] => 'int');
$ffi->attach('GDALMDArrayGetNoDataValueAsUInt64' => [qw/opaque int*/] => 'uint64');
$ffi->attach('GDALMDArraySetRawNoDataValue' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALMDArraySetNoDataValueAsDouble' => [qw/opaque double/] => 'int');
$ffi->attach('GDALMDArraySetNoDataValueAsInt64' => [qw/opaque int/] => 'int');
$ffi->attach('GDALMDArraySetNoDataValueAsUInt64' => [qw/opaque uint64/] => 'int');
$ffi->attach('GDALMDArraySetScale' => [qw/opaque double/] => 'int');
$ffi->attach('GDALMDArraySetScaleEx' => ['opaque','double','unsigned int'] => 'int');
$ffi->attach('GDALMDArrayGetScale' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALMDArrayGetScaleEx' => ['opaque','int*','unsigned int'] => 'double');
$ffi->attach('GDALMDArraySetOffset' => [qw/opaque double/] => 'int');
$ffi->attach('GDALMDArraySetOffsetEx' => ['opaque','double','unsigned int'] => 'int');
$ffi->attach('GDALMDArrayGetOffset' => [qw/opaque int*/] => 'double');
$ffi->attach('GDALMDArrayGetOffsetEx' => ['opaque','int*','unsigned int'] => 'double');
$ffi->attach('GDALMDArrayGetBlockSize' => [qw/opaque size_t/] => 'uint64');
$ffi->attach('GDALMDArraySetUnit' => [qw/opaque string/] => 'int');
$ffi->attach('GDALMDArrayGetUnit' => [qw/opaque/] => 'string');
$ffi->attach('GDALMDArraySetSpatialRef' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALMDArrayGetSpatialRef' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALMDArrayGetProcessingChunkSize' => [qw/opaque size_t size_t/] => 'size_t');
$ffi->attach('GDALMDArrayGetStructuralInfo' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALMDArrayGetView' => [qw/opaque string/] => 'opaque');
$ffi->attach('GDALMDArrayTranspose' => [qw/opaque size_t int*/] => 'opaque');
$ffi->attach('GDALMDArrayGetUnscaled' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALMDArrayGetMask' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALMDArrayAsClassicDataset' => [qw/opaque size_t size_t/] => 'opaque');
$ffi->attach('GDALMDArrayGetStatistics' => [qw/opaque opaque int int double* double* double* double* uint64 GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALMDArrayComputeStatistics' => [qw/opaque opaque int double* double* double* double* uint64 GDALProgressFunc opaque/] => 'int');
$ffi->attach('GDALMDArrayGetResampled' => [qw/opaque size_t opaque int opaque opaque/] => 'opaque');
$ffi->attach('GDALMDArrayGetGridded' => [qw/opaque string opaque opaque opaque/] => 'opaque');
$ffi->attach('GDALMDArrayGetCoordinateVariables' => [qw/opaque size_t/] => 'uint64*');
$ffi->attach('GDALReleaseArrays' => [qw/uint64* size_t/] => 'void');
$ffi->attach('GDALMDArrayCache' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALAttributeRelease' => [qw/opaque/] => 'void');
$ffi->attach('GDALReleaseAttributes' => [qw/uint64* size_t/] => 'void');
$ffi->attach('GDALAttributeGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALAttributeGetFullName' => [qw/opaque/] => 'string');
$ffi->attach('GDALAttributeGetTotalElementsCount' => [qw/opaque/] => 'uint64');
$ffi->attach('GDALAttributeGetDimensionCount' => [qw/opaque/] => 'size_t');
$ffi->attach('GDALAttributeGetDimensionsSize' => [qw/opaque size_t/] => 'uint64');
$ffi->attach('GDALAttributeGetDataType' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALAttributeReadAsRaw' => [qw/opaque size_t/] => 'pointer');
$ffi->attach('GDALAttributeFreeRawResult' => [qw/opaque pointer size_t/] => 'void');
$ffi->attach('GDALAttributeReadAsString' => [qw/opaque/] => 'string');
$ffi->attach('GDALAttributeReadAsInt' => [qw/opaque/] => 'int');
$ffi->attach('GDALAttributeReadAsDouble' => [qw/opaque/] => 'double');
$ffi->attach('GDALAttributeReadAsStringArray' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALAttributeReadAsIntArray' => [qw/opaque size_t/] => 'int*');
$ffi->attach('GDALAttributeReadAsDoubleArray' => [qw/opaque size_t/] => 'double*');
$ffi->attach('GDALAttributeWriteRaw' => [qw/opaque opaque size_t/] => 'int');
$ffi->attach('GDALAttributeWriteString' => [qw/opaque string/] => 'int');
$ffi->attach('GDALAttributeWriteStringArray' => [qw/opaque opaque/] => 'int');
$ffi->attach('GDALAttributeWriteInt' => [qw/opaque int/] => 'int');
$ffi->attach('GDALAttributeWriteDouble' => [qw/opaque double/] => 'int');
$ffi->attach('GDALAttributeWriteDoubleArray' => [qw/opaque double* size_t/] => 'int');
$ffi->attach('GDALDimensionRelease' => [qw/opaque/] => 'void');
$ffi->attach('GDALReleaseDimensions' => [qw/uint64* size_t/] => 'void');
$ffi->attach('GDALDimensionGetName' => [qw/opaque/] => 'string');
$ffi->attach('GDALDimensionGetFullName' => [qw/opaque/] => 'string');
$ffi->attach('GDALDimensionGetType' => [qw/opaque/] => 'string');
$ffi->attach('GDALDimensionGetDirection' => [qw/opaque/] => 'string');
$ffi->attach('GDALDimensionGetSize' => [qw/opaque/] => 'uint64');
$ffi->attach('GDALDimensionGetIndexingVariable' => [qw/opaque/] => 'opaque');
$ffi->attach('GDALDimensionSetIndexingVariable' => [qw/opaque opaque/] => 'int');
# from ogr/ogr_api.h
$ffi->attach('OGRGetGEOSVersion' => [qw/int* int* int*/] => 'bool');
$ffi->attach('OGR_G_CreateFromWkb' => [qw/string opaque uint64* int/] => 'int');
$ffi->attach('OGR_G_CreateFromWkbEx' => [qw/opaque opaque uint64* size_t/] => 'int');
$ffi->attach('OGR_G_CreateFromWkt' => [qw/string* opaque uint64*/] => 'int');
$ffi->attach('OGR_G_CreateFromFgf' => [qw/string opaque uint64* int int*/] => 'int');
$ffi->attach('OGR_G_DestroyGeometry' => [qw/opaque/] => 'void');
$ffi->attach('OGR_G_CreateGeometry' => ['unsigned int'] => 'opaque');
$ffi->attach('OGR_G_ApproximateArcAngles' => [qw/double double double double double double double double double/] => 'opaque');
$ffi->attach('OGR_G_ForceToPolygon' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ForceToLineString' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ForceToMultiPolygon' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ForceToMultiPoint' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ForceToMultiLineString' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ForceTo' => ['opaque','unsigned int','opaque'] => 'opaque');
$ffi->attach('OGR_G_RemoveLowerDimensionSubGeoms' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_GetDimension' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_GetCoordinateDimension' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_CoordinateDimension' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_SetCoordinateDimension' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_G_Is3D' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_IsMeasured' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_Set3D' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_G_SetMeasured' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_G_Clone' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_GetEnvelope' => [qw/opaque double[4]/] => 'void');
$ffi->attach('OGR_G_GetEnvelope3D' => [qw/opaque double[6]/] => 'void');
$ffi->attach('OGR_G_ImportFromWkb' => [qw/opaque string int/] => 'int');
$ffi->attach('OGR_G_ExportToWkb' => ['opaque','unsigned int','string'] => 'int');
$ffi->attach('OGR_G_ExportToIsoWkb' => ['opaque','unsigned int','string'] => 'int');
$ffi->attach('OGR_G_WkbSize' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_WkbSizeEx' => [qw/opaque/] => 'size_t');
$ffi->attach('OGR_G_ImportFromWkt' => [qw/opaque string*/] => 'int');
$ffi->attach('OGR_G_ExportToWkt' => [qw/opaque string*/] => 'int');
$ffi->attach('OGR_G_ExportToIsoWkt' => [qw/opaque string*/] => 'int');
$ffi->attach('OGR_G_GetGeometryType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_G_GetGeometryName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_G_DumpReadable' => [qw/opaque opaque string/] => 'void');
$ffi->attach('OGR_G_FlattenTo2D' => [qw/opaque/] => 'void');
$ffi->attach('OGR_G_CloseRings' => [qw/opaque/] => 'void');
$ffi->attach('OGR_G_CreateFromGML' => [qw/string/] => 'opaque');
$ffi->attach('OGR_G_ExportToGML' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ExportToGMLEx' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_CreateFromGMLTree' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ExportToGMLTree' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ExportEnvelopeToGMLTree' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ExportToKML' => [qw/opaque string/] => 'opaque');
$ffi->attach('OGR_G_ExportToJson' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ExportToJsonEx' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_CreateGeometryFromJson' => [qw/string/] => 'opaque');
$ffi->attach('OGR_G_CreateGeometryFromEsriJson' => [qw/string/] => 'opaque');
$ffi->attach('OGR_G_AssignSpatialReference' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_G_GetSpatialReference' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_Transform' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_TransformTo' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_GeomTransformer_Create' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_GeomTransformer_Transform' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_GeomTransformer_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_G_Simplify' => [qw/opaque double/] => 'opaque');
$ffi->attach('OGR_G_SimplifyPreserveTopology' => [qw/opaque double/] => 'opaque');
$ffi->attach('OGR_G_DelaunayTriangulation' => [qw/opaque double int/] => 'opaque');
$ffi->attach('OGR_G_Segmentize' => [qw/opaque double/] => 'bool');
$ffi->attach('OGR_G_Intersects' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Equals' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Disjoint' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Touches' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Crosses' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Within' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Contains' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Overlaps' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Boundary' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ConvexHull' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_ConcaveHull' => [qw/opaque double bool/] => 'opaque');
$ffi->attach('OGR_G_Buffer' => [qw/opaque double int/] => 'opaque');
$ffi->attach('OGR_G_Intersection' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_Union' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_UnionCascaded' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_UnaryUnion' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_PointOnSurface' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_Difference' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_SymDifference' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_Distance' => [qw/opaque opaque/] => 'double');
$ffi->attach('OGR_G_Distance3D' => [qw/opaque opaque/] => 'double');
$ffi->attach('OGR_G_Length' => [qw/opaque/] => 'double');
$ffi->attach('OGR_G_Area' => [qw/opaque/] => 'double');
$ffi->attach('OGR_G_Centroid' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Value' => [qw/opaque double/] => 'opaque');
$ffi->attach('OGR_G_Empty' => [qw/opaque/] => 'void');
$ffi->attach('OGR_G_IsEmpty' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_IsValid' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_MakeValid' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_MakeValidEx' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_Normalize' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_IsSimple' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_IsRing' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_Polygonize' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_Intersect' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_Equal' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_SymmetricDifference' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGR_G_GetArea' => [qw/opaque/] => 'double');
$ffi->attach('OGR_G_GetBoundary' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_G_GetPointCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_GetPoints' => [qw/opaque opaque int opaque int opaque int/] => 'int');
$ffi->attach('OGR_G_GetPointsZM' => [qw/opaque opaque int opaque int opaque int opaque int/] => 'int');
$ffi->attach('OGR_G_GetX' => [qw/opaque int/] => 'double');
$ffi->attach('OGR_G_GetY' => [qw/opaque int/] => 'double');
$ffi->attach('OGR_G_GetZ' => [qw/opaque int/] => 'double');
$ffi->attach('OGR_G_GetM' => [qw/opaque int/] => 'double');
$ffi->attach('OGR_G_GetPoint' => [qw/opaque int double* double* double*/] => 'void');
$ffi->attach('OGR_G_GetPointZM' => [qw/opaque int double* double* double* double*/] => 'void');
$ffi->attach('OGR_G_SetPointCount' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_G_SetPoint' => [qw/opaque int double double double/] => 'void');
$ffi->attach('OGR_G_SetPoint_2D' => [qw/opaque int double double/] => 'void');
$ffi->attach('OGR_G_SetPointM' => [qw/opaque int double double double/] => 'void');
$ffi->attach('OGR_G_SetPointZM' => [qw/opaque int double double double double/] => 'void');
$ffi->attach('OGR_G_AddPoint' => [qw/opaque double double double/] => 'void');
$ffi->attach('OGR_G_AddPoint_2D' => [qw/opaque double double/] => 'void');
$ffi->attach('OGR_G_AddPointM' => [qw/opaque double double double/] => 'void');
$ffi->attach('OGR_G_AddPointZM' => [qw/opaque double double double double/] => 'void');
$ffi->attach('OGR_G_SetPoints' => [qw/opaque int opaque int opaque int opaque int/] => 'void');
$ffi->attach('OGR_G_SetPointsZM' => [qw/opaque int opaque int opaque int opaque int opaque int/] => 'void');
$ffi->attach('OGR_G_SwapXY' => [qw/opaque/] => 'void');
$ffi->attach('OGR_G_GetGeometryCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_G_GetGeometryRef' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_G_AddGeometry' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_AddGeometryDirectly' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_G_RemoveGeometry' => [qw/opaque int int/] => 'int');
$ffi->attach('OGR_G_HasCurveGeometry' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_G_GetLinearGeometry' => [qw/opaque double opaque/] => 'opaque');
$ffi->attach('OGR_G_GetCurveGeometry' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OGRBuildPolygonFromEdges' => [qw/opaque int int double int*/] => 'opaque');
$ffi->attach('OGRSetGenerate_DB2_V72_BYTE_ORDER' => [qw/int/] => 'int');
$ffi->attach('OGRGetGenerate_DB2_V72_BYTE_ORDER' => [] => 'int');
$ffi->attach('OGRSetNonLinearGeometriesEnabledFlag' => [qw/int/] => 'void');
$ffi->attach('OGRGetNonLinearGeometriesEnabledFlag' => [] => 'int');
$ffi->attach('OGRHasPreparedGeometrySupport' => [] => 'int');
$ffi->attach('OGRCreatePreparedGeometry' => [qw/opaque/] => 'opaque');
$ffi->attach('OGRDestroyPreparedGeometry' => [qw/opaque/] => 'void');
$ffi->attach('OGRPreparedGeometryIntersects' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGRPreparedGeometryContains' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_Fld_Create' => ['string','unsigned int'] => 'opaque');
$ffi->attach('OGR_Fld_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_Fld_SetName' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_Fld_GetNameRef' => [qw/opaque/] => 'string');
$ffi->attach('OGR_Fld_SetAlternativeName' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_Fld_GetAlternativeNameRef' => [qw/opaque/] => 'string');
$ffi->attach('OGR_Fld_GetType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_Fld_SetType' => ['opaque','unsigned int'] => 'void');
$ffi->attach('OGR_Fld_GetSubType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_Fld_SetSubType' => ['opaque','unsigned int'] => 'void');
$ffi->attach('OGR_Fld_GetJustify' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_Fld_SetJustify' => ['opaque','unsigned int'] => 'void');
$ffi->attach('OGR_Fld_GetWidth' => [qw/opaque/] => 'int');
$ffi->attach('OGR_Fld_SetWidth' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_Fld_GetPrecision' => [qw/opaque/] => 'int');
$ffi->attach('OGR_Fld_SetPrecision' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_Fld_Set' => ['opaque','string','unsigned int','int','int','unsigned int'] => 'void');
$ffi->attach('OGR_Fld_IsIgnored' => [qw/opaque/] => 'int');
$ffi->attach('OGR_Fld_SetIgnored' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_Fld_IsNullable' => [qw/opaque/] => 'int');
$ffi->attach('OGR_Fld_SetNullable' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_Fld_IsUnique' => [qw/opaque/] => 'int');
$ffi->attach('OGR_Fld_SetUnique' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_Fld_GetDefault' => [qw/opaque/] => 'string');
$ffi->attach('OGR_Fld_SetDefault' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_Fld_IsDefaultDriverSpecific' => [qw/opaque/] => 'int');
$ffi->attach('OGR_Fld_GetDomainName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_Fld_SetDomainName' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_Fld_GetComment' => [qw/opaque/] => 'string');
$ffi->attach('OGR_Fld_SetComment' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_GetFieldTypeName' => ['unsigned int'] => 'string');
$ffi->attach('OGR_GetFieldSubTypeName' => ['unsigned int'] => 'string');
$ffi->attach('OGR_AreTypeSubTypeCompatible' => ['unsigned int','unsigned int'] => 'int');
$ffi->attach('OGR_GFld_Create' => ['string','unsigned int'] => 'opaque');
$ffi->attach('OGR_GFld_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_GFld_SetName' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_GFld_GetNameRef' => [qw/opaque/] => 'string');
$ffi->attach('OGR_GFld_GetType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_GFld_SetType' => ['opaque','unsigned int'] => 'void');
$ffi->attach('OGR_GFld_GetSpatialRef' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_GFld_SetSpatialRef' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_GFld_IsNullable' => [qw/opaque/] => 'int');
$ffi->attach('OGR_GFld_SetNullable' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_GFld_IsIgnored' => [qw/opaque/] => 'int');
$ffi->attach('OGR_GFld_SetIgnored' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_FD_Create' => [qw/string/] => 'opaque');
$ffi->attach('OGR_FD_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_FD_Release' => [qw/opaque/] => 'void');
$ffi->attach('OGR_FD_GetName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_FD_GetFieldCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_GetFieldDefn' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_FD_GetFieldIndex' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_FD_AddFieldDefn' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_FD_DeleteFieldDefn' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_FD_ReorderFieldDefns' => [qw/opaque int*/] => 'int');
$ffi->attach('OGR_FD_GetGeomType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_FD_SetGeomType' => ['opaque','unsigned int'] => 'void');
$ffi->attach('OGR_FD_IsGeometryIgnored' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_SetGeometryIgnored' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_FD_IsStyleIgnored' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_SetStyleIgnored' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_FD_Reference' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_Dereference' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_GetReferenceCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_GetGeomFieldCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FD_GetGeomFieldDefn' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_FD_GetGeomFieldIndex' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_FD_AddGeomFieldDefn' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_FD_DeleteGeomFieldDefn' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_FD_IsSame' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_F_Create' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_F_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_F_GetDefnRef' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_F_SetGeometryDirectly' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_F_SetGeometry' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_F_GetGeometryRef' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_F_StealGeometry' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_F_StealGeometryEx' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_F_Clone' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_F_Equal' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_F_GetFieldCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_F_GetFieldDefnRef' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_F_GetFieldIndex' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_F_IsFieldSet' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_F_UnsetField' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_F_IsFieldNull' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_F_IsFieldSetAndNotNull' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_F_SetFieldNull' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_F_GetRawFieldRef' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_RawField_IsUnset' => [qw/opaque/] => 'int');
$ffi->attach('OGR_RawField_IsNull' => [qw/opaque/] => 'int');
$ffi->attach('OGR_RawField_SetUnset' => [qw/opaque/] => 'void');
$ffi->attach('OGR_RawField_SetNull' => [qw/opaque/] => 'void');
$ffi->attach('OGR_F_GetFieldAsInteger' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_F_GetFieldAsInteger64' => [qw/opaque int/] => 'sint64');
$ffi->attach('OGR_F_GetFieldAsDouble' => [qw/opaque int/] => 'double');
$ffi->attach('OGR_F_GetFieldAsString' => [qw/opaque int/] => 'string');
$ffi->attach('OGR_F_GetFieldAsISO8601DateTime' => [qw/opaque int opaque/] => 'string');
$ffi->attach('OGR_F_GetFieldAsIntegerList' => [qw/opaque int int*/] => 'pointer');
$ffi->attach('OGR_F_GetFieldAsInteger64List' => [qw/opaque int int*/] => 'pointer');
$ffi->attach('OGR_F_GetFieldAsDoubleList' => [qw/opaque int int*/] => 'pointer');
$ffi->attach('OGR_F_GetFieldAsStringList' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_F_GetFieldAsBinary' => [qw/opaque int int*/] => 'pointer');
$ffi->attach('OGR_F_GetFieldAsDateTime' => [qw/opaque int int* int* int* int* int* int* int*/] => 'int');
$ffi->attach('OGR_F_GetFieldAsDateTimeEx' => [qw/opaque int int* int* int* int* int* float* int*/] => 'int');
$ffi->attach('OGR_F_SetFieldInteger' => [qw/opaque int int/] => 'void');
$ffi->attach('OGR_F_SetFieldInteger64' => [qw/opaque int sint64/] => 'void');
$ffi->attach('OGR_F_SetFieldDouble' => [qw/opaque int double/] => 'void');
$ffi->attach('OGR_F_SetFieldString' => [qw/opaque int string/] => 'void');
$ffi->attach('OGR_F_SetFieldIntegerList' => [qw/opaque int int int[]/] => 'void');
$ffi->attach('OGR_F_SetFieldInteger64List' => [qw/opaque int int sint64[]/] => 'void');
$ffi->attach('OGR_F_SetFieldDoubleList' => [qw/opaque int int double[]/] => 'void');
$ffi->attach('OGR_F_SetFieldStringList' => [qw/opaque int opaque/] => 'void');
$ffi->attach('OGR_F_SetFieldRaw' => [qw/opaque int opaque/] => 'void');
$ffi->attach('OGR_F_SetFieldBinary' => [qw/opaque int int opaque/] => 'void');
$ffi->attach('OGR_F_SetFieldDateTime' => [qw/opaque int int int int int int int int/] => 'void');
$ffi->attach('OGR_F_SetFieldDateTimeEx' => [qw/opaque int int int int int int float int/] => 'void');
$ffi->attach('OGR_F_GetGeomFieldCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_F_GetGeomFieldDefnRef' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_F_GetGeomFieldIndex' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_F_GetGeomFieldRef' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_F_SetGeomFieldDirectly' => [qw/opaque int opaque/] => 'int');
$ffi->attach('OGR_F_SetGeomField' => [qw/opaque int opaque/] => 'int');
$ffi->attach('OGR_F_GetFID' => [qw/opaque/] => 'sint64');
$ffi->attach('OGR_F_SetFID' => [qw/opaque sint64/] => 'int');
$ffi->attach('OGR_F_DumpReadable' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_F_SetFrom' => [qw/opaque opaque int/] => 'int');
$ffi->attach('OGR_F_SetFromWithMap' => [qw/opaque opaque int int*/] => 'int');
$ffi->attach('OGR_F_GetStyleString' => [qw/opaque/] => 'string');
$ffi->attach('OGR_F_SetStyleString' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_F_SetStyleStringDirectly' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_F_GetStyleTable' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_F_SetStyleTableDirectly' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_F_SetStyleTable' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_F_GetNativeData' => [qw/opaque/] => 'string');
$ffi->attach('OGR_F_SetNativeData' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_F_GetNativeMediaType' => [qw/opaque/] => 'string');
$ffi->attach('OGR_F_SetNativeMediaType' => [qw/opaque string/] => 'void');
$ffi->attach('OGR_F_FillUnsetWithDefault' => [qw/opaque int opaque/] => 'void');
$ffi->attach('OGR_F_Validate' => [qw/opaque int int/] => 'int');
$ffi->attach('OGR_FldDomain_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_FldDomain_GetName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_FldDomain_GetDescription' => [qw/opaque/] => 'string');
$ffi->attach('OGR_FldDomain_GetDomainType' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FldDomain_GetFieldType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_FldDomain_GetFieldSubType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_FldDomain_GetSplitPolicy' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FldDomain_SetSplitPolicy' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_FldDomain_GetMergePolicy' => [qw/opaque/] => 'int');
$ffi->attach('OGR_FldDomain_SetMergePolicy' => [qw/opaque int/] => 'void');
$ffi->attach('OGR_CodedFldDomain_Create' => ['string','string','unsigned int','unsigned int','int'] => 'opaque');
$ffi->attach('OGR_CodedFldDomain_GetEnumeration' => [qw/opaque/] => 'int');
$ffi->attach('OGR_RangeFldDomain_Create' => ['string','string','unsigned int','unsigned int','opaque','bool','opaque','bool'] => 'opaque');
$ffi->attach('OGR_RangeFldDomain_GetMin' => [qw/opaque bool/] => 'opaque');
$ffi->attach('OGR_RangeFldDomain_GetMax' => [qw/opaque bool/] => 'opaque');
$ffi->attach('OGR_GlobFldDomain_Create' => ['string','string','unsigned int','unsigned int','string'] => 'opaque');
$ffi->attach('OGR_GlobFldDomain_GetGlob' => [qw/opaque/] => 'string');
$ffi->attach('OGR_L_GetName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_L_GetGeomType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_L_GetGeometryTypes' => [qw/opaque int int int* GDALProgressFunc opaque/] => 'opaque');
$ffi->attach('OGR_L_GetSpatialFilter' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_L_SetSpatialFilter' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_L_SetSpatialFilterRect' => [qw/opaque double double double double/] => 'void');
$ffi->attach('OGR_L_SetSpatialFilterEx' => [qw/opaque int opaque/] => 'void');
$ffi->attach('OGR_L_SetSpatialFilterRectEx' => [qw/opaque int double double double double/] => 'void');
$ffi->attach('OGR_L_SetAttributeFilter' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_L_ResetReading' => [qw/opaque/] => 'void');
$ffi->attach('OGR_L_GetNextFeature' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_L_GetArrowStream' => [qw/opaque opaque opaque/] => 'bool');
$ffi->attach('OGR_L_SetNextByIndex' => [qw/opaque sint64/] => 'int');
$ffi->attach('OGR_L_GetFeature' => [qw/opaque sint64/] => 'opaque');
$ffi->attach('OGR_L_SetFeature' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_L_CreateFeature' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_L_DeleteFeature' => [qw/opaque sint64/] => 'int');
$ffi->attach('OGR_L_UpsertFeature' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_L_UpdateFeature' => [qw/opaque opaque int int* int int* bool/] => 'int');
$ffi->attach('OGR_L_GetLayerDefn' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_L_GetSpatialRef' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_L_GetSupportedSRSList' => [qw/opaque int int*/] => 'uint64*');
$ffi->attach('OGR_L_SetActiveSRS' => [qw/opaque int opaque/] => 'int');
$ffi->attach('OGR_L_FindFieldIndex' => [qw/opaque string int/] => 'int');
$ffi->attach('OGR_L_GetFeatureCount' => [qw/opaque int/] => 'sint64');
$ffi->attach('OGR_L_GetExtent' => [qw/opaque double[4] int/] => 'int');
$ffi->attach('OGR_L_GetExtentEx' => [qw/opaque int double[4] int/] => 'int');
$ffi->attach('OGR_L_TestCapability' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_L_CreateField' => [qw/opaque opaque int/] => 'int');
$ffi->attach('OGR_L_CreateGeomField' => [qw/opaque opaque int/] => 'int');
$ffi->attach('OGR_L_DeleteField' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_L_ReorderFields' => [qw/opaque int*/] => 'int');
$ffi->attach('OGR_L_ReorderField' => [qw/opaque int int/] => 'int');
$ffi->attach('OGR_L_AlterFieldDefn' => [qw/opaque int opaque int/] => 'int');
$ffi->attach('OGR_L_AlterGeomFieldDefn' => [qw/opaque int opaque int/] => 'int');
$ffi->attach('OGR_L_StartTransaction' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_CommitTransaction' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_RollbackTransaction' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_Rename' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_L_Reference' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_Dereference' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_GetRefCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_SyncToDisk' => [qw/opaque/] => 'int');
$ffi->attach('OGR_L_GetFeaturesRead' => [qw/opaque/] => 'sint64');
$ffi->attach('OGR_L_GetFIDColumn' => [qw/opaque/] => 'string');
$ffi->attach('OGR_L_GetGeometryColumn' => [qw/opaque/] => 'string');
$ffi->attach('OGR_L_GetStyleTable' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_L_SetStyleTableDirectly' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_L_SetStyleTable' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_L_SetIgnoredFields' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_L_Intersection' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_L_Union' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_L_SymDifference' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_L_Identity' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_L_Update' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_L_Clip' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_L_Erase' => [qw/opaque opaque opaque opaque GDALProgressFunc opaque/] => 'int');
$ffi->attach('OGR_DS_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_DS_GetName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_DS_GetLayerCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_DS_GetLayer' => [qw/opaque int/] => 'opaque');
$ffi->attach('OGR_DS_GetLayerByName' => [qw/opaque string/] => 'opaque');
$ffi->attach('OGR_DS_DeleteLayer' => [qw/opaque int/] => 'int');
$ffi->attach('OGR_DS_GetDriver' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_DS_CreateLayer' => ['opaque','string','opaque','unsigned int','opaque'] => 'opaque');
$ffi->attach('OGR_DS_CopyLayer' => [qw/opaque opaque string opaque/] => 'opaque');
$ffi->attach('OGR_DS_TestCapability' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_DS_ExecuteSQL' => [qw/opaque string opaque string/] => 'opaque');
$ffi->attach('OGR_DS_ReleaseResultSet' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_DS_Reference' => [qw/opaque/] => 'int');
$ffi->attach('OGR_DS_Dereference' => [qw/opaque/] => 'int');
$ffi->attach('OGR_DS_GetRefCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_DS_GetSummaryRefCount' => [qw/opaque/] => 'int');
$ffi->attach('OGR_DS_SyncToDisk' => [qw/opaque/] => 'int');
$ffi->attach('OGR_DS_GetStyleTable' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_DS_SetStyleTableDirectly' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_DS_SetStyleTable' => [qw/opaque opaque/] => 'void');
$ffi->attach('OGR_Dr_GetName' => [qw/opaque/] => 'string');
$ffi->attach('OGR_Dr_Open' => [qw/opaque string int/] => 'opaque');
$ffi->attach('OGR_Dr_TestCapability' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_Dr_CreateDataSource' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('OGR_Dr_CopyDataSource' => [qw/opaque opaque string opaque/] => 'opaque');
$ffi->attach('OGR_Dr_DeleteDataSource' => [qw/opaque string/] => 'int');
$ffi->attach('OGROpen' => [qw/string int uint64*/] => 'opaque');
$ffi->attach('OGROpenShared' => [qw/string int uint64*/] => 'opaque');
$ffi->attach('OGRReleaseDataSource' => [qw/opaque/] => 'int');
$ffi->attach('OGRRegisterDriver' => [qw/opaque/] => 'void');
$ffi->attach('OGRDeregisterDriver' => [qw/opaque/] => 'void');
$ffi->attach('OGRGetDriverCount' => [] => 'int');
$ffi->attach('OGRGetDriver' => [qw/int/] => 'opaque');
$ffi->attach('OGRGetDriverByName' => [qw/string/] => 'opaque');
$ffi->attach('OGRGetOpenDSCount' => [] => 'int');
$ffi->attach('OGRGetOpenDS' => [qw/int/] => 'opaque');
$ffi->attach('OGRRegisterAll' => [] => 'void');
$ffi->attach('OGRCleanupAll' => [] => 'void');
$ffi->attach('OGR_SM_Create' => [qw/opaque/] => 'opaque');
$ffi->attach('OGR_SM_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_SM_InitFromFeature' => [qw/opaque opaque/] => 'string');
$ffi->attach('OGR_SM_InitStyleString' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_SM_GetPartCount' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_SM_GetPart' => [qw/opaque int string/] => 'opaque');
$ffi->attach('OGR_SM_AddPart' => [qw/opaque opaque/] => 'int');
$ffi->attach('OGR_SM_AddStyle' => [qw/opaque string string/] => 'int');
$ffi->attach('OGR_ST_Create' => ['unsigned int'] => 'opaque');
$ffi->attach('OGR_ST_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_ST_GetType' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_ST_GetUnit' => [qw/opaque/] => 'unsigned int');
$ffi->attach('OGR_ST_SetUnit' => ['opaque','unsigned int','double'] => 'void');
$ffi->attach('OGR_ST_GetParamStr' => [qw/opaque int int*/] => 'string');
$ffi->attach('OGR_ST_GetParamNum' => [qw/opaque int int*/] => 'int');
$ffi->attach('OGR_ST_GetParamDbl' => [qw/opaque int int*/] => 'double');
$ffi->attach('OGR_ST_SetParamStr' => [qw/opaque int string/] => 'void');
$ffi->attach('OGR_ST_SetParamNum' => [qw/opaque int int/] => 'void');
$ffi->attach('OGR_ST_SetParamDbl' => [qw/opaque int double/] => 'void');
$ffi->attach('OGR_ST_GetStyleString' => [qw/opaque/] => 'string');
$ffi->attach('OGR_ST_GetRGBFromString' => [qw/opaque string int* int* int* int*/] => 'int');
$ffi->attach('OGR_STBL_Create' => [] => 'opaque');
$ffi->attach('OGR_STBL_Destroy' => [qw/opaque/] => 'void');
$ffi->attach('OGR_STBL_AddStyle' => [qw/opaque string string/] => 'int');
$ffi->attach('OGR_STBL_SaveStyleTable' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_STBL_LoadStyleTable' => [qw/opaque string/] => 'int');
$ffi->attach('OGR_STBL_Find' => [qw/opaque string/] => 'string');
$ffi->attach('OGR_STBL_ResetStyleStringReading' => [qw/opaque/] => 'void');
$ffi->attach('OGR_STBL_GetNextStyle' => [qw/opaque/] => 'string');
$ffi->attach('OGR_STBL_GetLastStyleName' => [qw/opaque/] => 'string');
# from ogr/ogr_srs_api.h
$ffi->attach('OSRAxisEnumToName' => ['unsigned int'] => 'string');
$ffi->attach('OSRSetPROJSearchPaths' => [qw/opaque/] => 'void');
$ffi->attach('OSRGetPROJSearchPaths' => [] => 'opaque');
$ffi->attach('OSRSetPROJAuxDbPaths' => [qw/opaque/] => 'void');
$ffi->attach('OSRGetPROJAuxDbPaths' => [] => 'opaque');
$ffi->attach('OSRSetPROJEnableNetwork' => [qw/int/] => 'void');
$ffi->attach('OSRGetPROJEnableNetwork' => [] => 'int');
$ffi->attach('OSRGetPROJVersion' => [qw/int* int* int*/] => 'void');
$ffi->attach('OSRNewSpatialReference' => [qw/string/] => 'opaque');
$ffi->attach('OSRCloneGeogCS' => [qw/opaque/] => 'opaque');
$ffi->attach('OSRClone' => [qw/opaque/] => 'opaque');
$ffi->attach('OSRDestroySpatialReference' => [qw/opaque/] => 'void');
$ffi->attach('OSRReference' => [qw/opaque/] => 'int');
$ffi->attach('OSRDereference' => [qw/opaque/] => 'int');
$ffi->attach('OSRRelease' => [qw/opaque/] => 'void');
$ffi->attach('OSRValidate' => [qw/opaque/] => 'int');
$ffi->attach('OSRImportFromEPSG' => [qw/opaque int/] => 'int');
$ffi->attach('OSRImportFromEPSGA' => [qw/opaque int/] => 'int');
$ffi->attach('OSRImportFromWkt' => [qw/opaque string*/] => 'int');
$ffi->attach('OSRImportFromProj4' => [qw/opaque string/] => 'int');
$ffi->attach('OSRImportFromESRI' => [qw/opaque opaque/] => 'int');
$ffi->attach('OSRImportFromPCI' => [qw/opaque string string double*/] => 'int');
$ffi->attach('OSRImportFromUSGS' => [qw/opaque long long double* long/] => 'int');
$ffi->attach('OSRImportFromXML' => [qw/opaque string/] => 'int');
$ffi->attach('OSRImportFromDict' => [qw/opaque string string/] => 'int');
$ffi->attach('OSRImportFromPanorama' => [qw/opaque long long long double*/] => 'int');
$ffi->attach('OSRImportFromOzi' => [qw/opaque opaque/] => 'int');
$ffi->attach('OSRImportFromMICoordSys' => [qw/opaque string/] => 'int');
$ffi->attach('OSRImportFromERM' => [qw/opaque string string string/] => 'int');
$ffi->attach('OSRImportFromUrl' => [qw/opaque string/] => 'int');
$ffi->attach('OSRExportToWkt' => [qw/opaque string*/] => 'int');
$ffi->attach('OSRExportToWktEx' => [qw/opaque string* opaque/] => 'int');
$ffi->attach('OSRExportToPrettyWkt' => [qw/opaque string* int/] => 'int');
$ffi->attach('OSRExportToPROJJSON' => [qw/opaque string* opaque/] => 'int');
$ffi->attach('OSRExportToProj4' => [qw/opaque string*/] => 'int');
$ffi->attach('OSRExportToPCI' => [qw/opaque string* string* double*/] => 'int');
$ffi->attach('OSRExportToUSGS' => [qw/opaque long* long* double* long*/] => 'int');
$ffi->attach('OSRExportToXML' => [qw/opaque string* string/] => 'int');
$ffi->attach('OSRExportToPanorama' => [qw/opaque long* long* long* long* double*/] => 'int');
$ffi->attach('OSRExportToMICoordSys' => [qw/opaque string*/] => 'int');
$ffi->attach('OSRExportToERM' => [qw/opaque string string string/] => 'int');
$ffi->attach('OSRMorphToESRI' => [qw/opaque/] => 'int');
$ffi->attach('OSRMorphFromESRI' => [qw/opaque/] => 'int');
$ffi->attach('OSRStripVertical' => [qw/opaque/] => 'int');
$ffi->attach('OSRConvertToOtherProjection' => [qw/opaque string opaque/] => 'opaque');
$ffi->attach('OSRGetName' => [qw/opaque/] => 'string');
$ffi->attach('OSRSetAttrValue' => [qw/opaque string string/] => 'int');
$ffi->attach('OSRGetAttrValue' => [qw/opaque string int/] => 'string');
$ffi->attach('OSRSetAngularUnits' => [qw/opaque string double/] => 'int');
$ffi->attach('OSRGetAngularUnits' => [qw/opaque string*/] => 'double');
$ffi->attach('OSRSetLinearUnits' => [qw/opaque string double/] => 'int');
$ffi->attach('OSRSetTargetLinearUnits' => [qw/opaque string string double/] => 'int');
$ffi->attach('OSRSetLinearUnitsAndUpdateParameters' => [qw/opaque string double/] => 'int');
$ffi->attach('OSRGetLinearUnits' => [qw/opaque string*/] => 'double');
$ffi->attach('OSRGetTargetLinearUnits' => [qw/opaque string string*/] => 'double');
$ffi->attach('OSRGetPrimeMeridian' => [qw/opaque string*/] => 'double');
$ffi->attach('OSRIsGeographic' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsDerivedGeographic' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsLocal' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsProjected' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsCompound' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsGeocentric' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsVertical' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsDynamic' => [qw/opaque/] => 'int');
$ffi->attach('OSRIsSameGeogCS' => [qw/opaque opaque/] => 'int');
$ffi->attach('OSRIsSameVertCS' => [qw/opaque opaque/] => 'int');
$ffi->attach('OSRIsSame' => [qw/opaque opaque/] => 'int');
$ffi->attach('OSRIsSameEx' => [qw/opaque opaque opaque/] => 'int');
$ffi->attach('OSRSetCoordinateEpoch' => [qw/opaque double/] => 'void');
$ffi->attach('OSRGetCoordinateEpoch' => [qw/opaque/] => 'double');
$ffi->attach('OSRSetLocalCS' => [qw/opaque string/] => 'int');
$ffi->attach('OSRSetProjCS' => [qw/opaque string/] => 'int');
$ffi->attach('OSRSetGeocCS' => [qw/opaque string/] => 'int');
$ffi->attach('OSRSetWellKnownGeogCS' => [qw/opaque string/] => 'int');
$ffi->attach('OSRSetFromUserInput' => [qw/opaque string/] => 'int');
$ffi->attach('OSRCopyGeogCSFrom' => [qw/opaque opaque/] => 'int');
$ffi->attach('OSRSetTOWGS84' => [qw/opaque double double double double double double double/] => 'int');
$ffi->attach('OSRGetTOWGS84' => [qw/opaque double* int/] => 'int');
$ffi->attach('OSRAddGuessedTOWGS84' => [qw/opaque/] => 'int');
$ffi->attach('OSRSetCompoundCS' => [qw/opaque string opaque opaque/] => 'int');
$ffi->attach('OSRPromoteTo3D' => [qw/opaque string/] => 'int');
$ffi->attach('OSRDemoteTo2D' => [qw/opaque string/] => 'int');
$ffi->attach('OSRSetGeogCS' => [qw/opaque string string string double double string double string double/] => 'int');
$ffi->attach('OSRSetVertCS' => [qw/opaque string string int/] => 'int');
$ffi->attach('OSRGetSemiMajor' => [qw/opaque int*/] => 'double');
$ffi->attach('OSRGetSemiMinor' => [qw/opaque int*/] => 'double');
$ffi->attach('OSRGetInvFlattening' => [qw/opaque int*/] => 'double');
$ffi->attach('OSRSetAuthority' => [qw/opaque string string int/] => 'int');
$ffi->attach('OSRGetAuthorityCode' => [qw/opaque string/] => 'string');
$ffi->attach('OSRGetAuthorityName' => [qw/opaque string/] => 'string');
$ffi->attach('OSRGetAreaOfUse' => [qw/opaque double* double* double* double* string/] => 'int');
$ffi->attach('OSRSetProjection' => [qw/opaque string/] => 'int');
$ffi->attach('OSRSetProjParm' => [qw/opaque string double/] => 'int');
$ffi->attach('OSRGetProjParm' => [qw/opaque string double int*/] => 'double');
$ffi->attach('OSRSetNormProjParm' => [qw/opaque string double/] => 'int');
$ffi->attach('OSRGetNormProjParm' => [qw/opaque string double int*/] => 'double');
$ffi->attach('OSRSetUTM' => [qw/opaque int int/] => 'int');
$ffi->attach('OSRGetUTMZone' => [qw/opaque int*/] => 'int');
$ffi->attach('OSRSetStatePlane' => [qw/opaque int int/] => 'int');
$ffi->attach('OSRSetStatePlaneWithUnits' => [qw/opaque int int string double/] => 'int');
$ffi->attach('OSRAutoIdentifyEPSG' => [qw/opaque/] => 'int');
$ffi->attach('OSRFindMatches' => [qw/opaque opaque int* int*/] => 'uint64*');
$ffi->attach('OSRFreeSRSArray' => [qw/uint64*/] => 'void');
$ffi->attach('OSREPSGTreatsAsLatLong' => [qw/opaque/] => 'int');
$ffi->attach('OSREPSGTreatsAsNorthingEasting' => [qw/opaque/] => 'int');
$ffi->attach('OSRGetAxis' => ['opaque','string','int','unsigned int'] => 'string');
$ffi->attach('OSRGetAxesCount' => [qw/opaque/] => 'int');
$ffi->attach('OSRSetAxes' => ['opaque','string','string','unsigned int','string','unsigned int'] => 'int');
$ffi->attach('OSRGetAxisMappingStrategy' => [qw/opaque/] => 'int');
$ffi->attach('OSRSetAxisMappingStrategy' => [qw/opaque int/] => 'void');
$ffi->attach('OSRGetDataAxisToSRSAxisMapping' => [qw/opaque int*/] => 'int*');
$ffi->attach('OSRSetDataAxisToSRSAxisMapping' => [qw/opaque int int*/] => 'int');
$ffi->attach('OSRSetACEA' => [qw/opaque double double double double double double/] => 'int');
$ffi->attach('OSRSetAE' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetBonne' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetCEA' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetCS' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetEC' => [qw/opaque double double double double double double/] => 'int');
$ffi->attach('OSRSetEckert' => [qw/opaque int double double double/] => 'int');
$ffi->attach('OSRSetEckertIV' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetEckertVI' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetEquirectangular' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetEquirectangular2' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetGS' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetGH' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetIGH' => [qw/opaque/] => 'int');
$ffi->attach('OSRSetGEOS' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetGaussSchreiberTMercator' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetGnomonic' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetHOM' => [qw/opaque double double double double double double double/] => 'int');
$ffi->attach('OSRSetHOMAC' => [qw/opaque double double double double double double double/] => 'int');
$ffi->attach('OSRSetHOM2PNO' => [qw/opaque double double double double double double double double/] => 'int');
$ffi->attach('OSRSetIWMPolyconic' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetKrovak' => [qw/opaque double double double double double double double/] => 'int');
$ffi->attach('OSRSetLAEA' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetLCC' => [qw/opaque double double double double double double/] => 'int');
$ffi->attach('OSRSetLCC1SP' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetLCCB' => [qw/opaque double double double double double double/] => 'int');
$ffi->attach('OSRSetMC' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetMercator' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetMercator2SP' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetMollweide' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetNZMG' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetOS' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetOrthographic' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetPolyconic' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetPS' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetRobinson' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetSinusoidal' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetStereographic' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetSOC' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetTM' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetTMVariant' => [qw/opaque string double double double double double/] => 'int');
$ffi->attach('OSRSetTMG' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetTMSO' => [qw/opaque double double double double double/] => 'int');
$ffi->attach('OSRSetTPED' => [qw/opaque double double double double double double/] => 'int');
$ffi->attach('OSRSetVDG' => [qw/opaque double double double/] => 'int');
$ffi->attach('OSRSetWagner' => [qw/opaque int double double double/] => 'int');
$ffi->attach('OSRSetQSC' => [qw/opaque double double/] => 'int');
$ffi->attach('OSRSetSCH' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OSRSetVerticalPerspective' => [qw/opaque double double double double double double/] => 'int');
$ffi->attach('OSRCalcInvFlattening' => [qw/double double/] => 'double');
$ffi->attach('OSRCalcSemiMinorFromInvFlattening' => [qw/double double/] => 'double');
$ffi->attach('OSRCleanup' => [] => 'void');
$ffi->attach('OSRGetCRSInfoListFromDatabase' => [qw/string opaque int*/] => 'opaque');
$ffi->attach('OSRDestroyCRSInfoList' => [qw/opaque/] => 'void');
$ffi->attach('OCTNewCoordinateTransformation' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('OCTNewCoordinateTransformationOptions' => [] => 'opaque');
$ffi->attach('OCTCoordinateTransformationOptionsSetOperation' => [qw/opaque string int/] => 'int');
$ffi->attach('OCTCoordinateTransformationOptionsSetAreaOfInterest' => [qw/opaque double double double double/] => 'int');
$ffi->attach('OCTCoordinateTransformationOptionsSetDesiredAccuracy' => [qw/opaque double/] => 'int');
$ffi->attach('OCTCoordinateTransformationOptionsSetBallparkAllowed' => [qw/opaque int/] => 'int');
$ffi->attach('OCTDestroyCoordinateTransformationOptions' => [qw/opaque/] => 'void');
$ffi->attach('OCTNewCoordinateTransformationEx' => [qw/opaque opaque opaque/] => 'opaque');
$ffi->attach('OCTClone' => [qw/opaque/] => 'opaque');
$ffi->attach('OCTGetSourceCS' => [qw/opaque/] => 'opaque');
$ffi->attach('OCTGetTargetCS' => [qw/opaque/] => 'opaque');
$ffi->attach('OCTGetInverse' => [qw/opaque/] => 'opaque');
$ffi->attach('OCTDestroyCoordinateTransformation' => [qw/opaque/] => 'void');
$ffi->attach('OCTTransform' => [qw/opaque int double[] double[] double[]/] => 'int');
$ffi->attach('OCTTransformEx' => [qw/opaque int double[] double[] double[] int[]/] => 'int');
$ffi->attach('OCTTransform4D' => [qw/opaque int double[] double[] double[] double[] int[]/] => 'int');
$ffi->attach('OCTTransform4DWithErrorCodes' => [qw/opaque int double[] double[] double[] double[] int[]/] => 'int');
$ffi->attach('OCTTransformBounds' => [qw/opaque double double double double double[] double[] double[] double[] int/] => 'int');
# from apps/gdal_utils.h
$ffi->attach('GDALInfoOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALInfoOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALInfo' => [qw/opaque opaque/] => 'string');
$ffi->attach('GDALTranslateOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALTranslateOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALTranslateOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALTranslate' => [qw/string opaque opaque int*/] => 'opaque');
$ffi->attach('GDALWarpAppOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALWarpAppOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALWarpAppOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALWarpAppOptionsSetQuiet' => [qw/opaque int/] => 'void');
$ffi->attach('GDALWarpAppOptionsSetWarpOption' => [qw/opaque string string/] => 'void');
$ffi->attach('GDALWarp' => [qw/string opaque int opaque[] opaque int*/] => 'opaque');
$ffi->attach('GDALVectorTranslateOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALVectorTranslateOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALVectorTranslateOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALVectorTranslate' => [qw/string opaque int opaque[] opaque int*/] => 'opaque');
$ffi->attach('GDALDEMProcessingOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALDEMProcessingOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALDEMProcessingOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALDEMProcessing' => [qw/string opaque string string opaque int*/] => 'opaque');
$ffi->attach('GDALNearblackOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALNearblackOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALNearblackOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALNearblack' => [qw/string opaque opaque opaque int*/] => 'opaque');
$ffi->attach('GDALGridOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALGridOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALGridOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALGrid' => [qw/string opaque opaque int*/] => 'opaque');
$ffi->attach('GDALRasterizeOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALRasterizeOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALRasterizeOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALRasterize' => [qw/string opaque opaque opaque int*/] => 'opaque');
$ffi->attach('GDALBuildVRTOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALBuildVRTOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALBuildVRTOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALBuildVRT' => [qw/string int opaque[] opaque opaque int*/] => 'opaque');
$ffi->attach('GDALMultiDimInfoOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALMultiDimInfoOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALMultiDimInfo' => [qw/opaque opaque/] => 'string');
$ffi->attach('GDALMultiDimTranslateOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALMultiDimTranslateOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALMultiDimTranslateOptionsSetProgress' => [qw/opaque GDALProgressFunc opaque/] => 'void');
$ffi->attach('GDALMultiDimTranslate' => [qw/string opaque int uint64* opaque int*/] => 'opaque');
$ffi->attach('GDALVectorInfoOptionsNew' => [qw/opaque opaque/] => 'opaque');
$ffi->attach('GDALVectorInfoOptionsFree' => [qw/opaque/] => 'void');
$ffi->attach('GDALVectorInfo' => [qw/opaque opaque/] => 'string');
# end of generated code
if ($gdal eq 'Alien::gdal' and versioncmp($gdal->version, '2.3.1') <= 0) {
# we do not use Alien::gdal->data_dir since it issues warnings due to GDAL bug
my $pc = PkgConfig->find('gdal');
if ($pc->errmsg) {
my $dir = Alien::gdal->dist_dir;
my %options = (search_path_override => ["$dir/lib/pkgconfig", "$dir/lib64/pkgconfig"]);
$pc = PkgConfig->find('gdal', %options);
}
if ($pc->errmsg) {
warn $pc->errmsg;
} else {
my $dir = $pc->get_var('datadir');
# this gdal.pc bug was fixed in GDAL 2.3.1
# we just hope the one configuring GDAL did not change it to something that ends '/data'
$dir =~ s/\/data$//;
if (opendir(my $dh, $dir)) {
CPLSetConfigOption(GDAL_DATA => $dir);
} else {
my $dist_data_dir = Alien::gdal->dist_dir . '/share/gdal';
if (-d $dist_data_dir) {
CPLSetConfigOption(GDAL_DATA => $dist_data_dir);
}
else {
warn "GDAL data directory ($dir) doesn't exist. Maybe Alien::gdal is not installed?";
}
}
}
} else {
CPLSetConfigOption(GDAL_DATA => $gdal->data_dir);
}
$instance = {};
$instance->{ffi} = $ffi;
$instance->{gdal} = $gdal;
SetErrorHandling();
GDALAllRegister();
return bless $instance, $class;
}
sub get_instance {
my $class = shift;
$instance = $class->new() unless $instance;
return $instance;
}
sub DESTROY {
UnsetErrorHandling();
}
sub GetVersionInfo {
my $request = shift // 'VERSION_NUM';
if ($request eq 'SEMANTIC') {
my $version = GDALVersionInfo('VERSION_NUM') / 100;
my $ret = '';
while ($version > 0) {
my $v = $version % 100;
$ret = ".$ret" if $ret ne '';
$ret = "$v$ret";
$version = int($version/100);
}
return $ret;
}
return GDALVersionInfo($request);
}
sub GetDriver {
my ($i) = @_;
my $d = isint($i) ? GDALGetDriver($i) : GDALGetDriverByName($i);
confess error_msg() // "Driver '$i' not found." unless $d;
return bless \$d, 'Geo::GDAL::FFI::Driver';
}
sub GetDrivers {
my @drivers;
for my $i (0..GDALGetDriverCount()-1) {
push @drivers, GetDriver($i);
}
return @drivers;
}
sub IdentifyDriver {
my ($filename, $args) = @_;
my $flags = 0;
my $a = $args->{Flags} // [];
for my $f (@$a) {
print "$f\n";
$flags |= $open_flags{$f};
}
print "$flags\n";
my $drivers = 0;
for my $o (@{$args->{AllowedDrivers}}) {
$drivers = Geo::GDAL::FFI::CSLAddString($drivers, $o);
}
my $list = 0;
for my $o (@{$args->{FileList}}) {
$list = Geo::GDAL::FFI::CSLAddString($list, $o);
}
my $d;
if ($flags or $drivers) {
$d = GDALIdentifyDriverEx($filename, $flags, $drivers, $list);
} else {
$d = GDALIdentifyDriver($filename, $list);
}
Geo::GDAL::FFI::CSLDestroy($drivers);
Geo::GDAL::FFI::CSLDestroy($list);
return bless \$d, 'Geo::GDAL::FFI::Driver';
}
sub Open {
my ($name, $args) = @_;
$name //= '';
$args //= {};
my $flags = 0;
my $a = $args->{Flags} // [];
for my $f (@$a) {
$flags |= $open_flags{$f};
}
my $drivers = 0;
for my $o (@{$args->{AllowedDrivers}}) {
$drivers = Geo::GDAL::FFI::CSLAddString($drivers, $o);
}
my $options = 0;
for my $o (@{$args->{Options}}) {
$options = Geo::GDAL::FFI::CSLAddString($options, $o);
}
my $files = 0;
for my $o (@{$args->{SiblingFiles}}) {
$files = Geo::GDAL::FFI::CSLAddString($files, $o);
}
my $ds = GDALOpenEx($name, $flags, $drivers, $options, $files);
Geo::GDAL::FFI::CSLDestroy($drivers);
Geo::GDAL::FFI::CSLDestroy($options);
Geo::GDAL::FFI::CSLDestroy($files);
if (@errors) {
my $msg = join("\n", @errors);
@errors = ();
confess $msg;
}
unless ($ds) { # no VERBOSE_ERROR in options and fail
confess "Open failed for '$name'. Hint: add VERBOSE_ERROR to open_flags.";
}
return bless \$ds, 'Geo::GDAL::FFI::Dataset';
}
sub write {
print STDOUT $_[0];
}
sub close {
}
sub SetWriter {
my ($self, $writer) = @_;
$writer = $self unless $writer;
my $w = $writer->can('write');
my $c = $writer->can('close');
confess "$writer must be able to write and close." unless $w && $c;
#$self->{write} = $w;
$self->{close} = $c;
$self->{writer} = $self->{ffi}->closure(sub {
my ($buf, $size, $count, $stream) = @_;
my $retval = $w->(buffer_to_scalar($buf, $size*$count)) // 1;
return $retval;
});
VSIStdoutSetRedirection($self->{writer}, 0);
}
sub CloseWriter {
my $self = shift;
$self->{close}->() if $self->{close};
$self->SetWriter;
}
sub get_importer {
my ($self, $format) = @_;
my $importer = $self->can('OSRImportFrom' . $format);
confess "Spatial reference importer for format '$format' not found!" unless $importer;
return $importer;
}
sub get_exporter {
my ($self, $format) = @_;
my $exporter = $self->can('OSRExportTo' . $format);
confess "Spatial reference exporter for format '$format' not found!" unless $exporter;
return $exporter;
}
sub get_setter {
my ($self, $proj) = @_;
my $setter = $self->can('OSRSet' . $proj);
confess "Parameter setter for projection '$proj' not found!" unless $setter;
return $setter;
}
sub HaveGEOS {
my $t = $geometry_types{Point};
my $g = OGR_G_CreateGeometry($t);
OGR_G_SetPoint($g, 0, 0, 0, 0);
my $c = OGR_G_CreateGeometry($t);
my $n = @errors;
OGR_G_Centroid($g, $c);
if (@errors > $n) {
pop @errors;
return undef;
} else {
return 1;
}
}
sub SetConfigOption {
my ($key, $default) = @_;
CPLSetConfigOption($key, $default);
}
sub GetConfigOption {
my ($key, $default) = @_;
return CPLGetConfigOption($key, $default);
}
sub FindFile {
my ($class, $basename) = @_ == 2 ? @_ : ('', @_);
$class //= '';
$basename //= '';
return CPLFindFile($class, $basename);
}
sub PushFinderLocation {
my ($location) = @_;
$location //= '';
CPLPushFinderLocation($location);
}
sub PopFinderLocation {
CPLPopFinderLocation();
}
sub FinderClean {
CPLFinderClean();
}
sub get_memory_driver {
use Sort::Versions qw /versioncmp/;
state $gdal_version = GetVersionInfo('SEMANTIC');
state $driver_name = versioncmp ($gdal_version, '3.11') >= 0 ? 'MEM' : 'Memory';
return $driver_name;
}
BEGIN {
require PkgConfig;
PkgConfig->import;
my $gdal;
eval {
require Geo::GDAL::gdal;
$gdal = Geo::GDAL::gdal->new();
};
if ($@) {
require Alien::gdal;
no strict 'subs';
$gdal = Alien::gdal;
}
$instance = Geo::GDAL::FFI->new($gdal);
}
{
# avoid some used only once warnings
local $FFI::Platypus::keep;
local $FFI::Platypus::TypeParser::ffi_type;
}
#
# The next two subs are required for thread-safety, because GDAL error handling must be set per thread.
# So, it is disabled just before starting a new thread and renabled after in the thread.
# See perlmod and issue #53 for more information.
#
sub CLONE {
SetErrorHandling();
}
sub CLONE_SKIP {
UnsetErrorHandling();
return 0;
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI - A foreign function interface to GDAL
=head1 SYNOPSIS
This is an example of creating a vector dataset.
use Geo::GDAL::FFI qw/GetDriver/;
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
my $layer = GetDriver('ESRI Shapefile')
->Create('test.shp')
->CreateLayer({
Name => 'test',
SpatialReference => $sr,
GeometryType => 'Point',
Fields => [
{
Name => 'name',
Type => 'String'
}
]
});
my $f = Geo::GDAL::FFI::Feature->new($layer->GetDefn);
$f->SetField(name => 'a');
my $g = Geo::GDAL::FFI::Geometry->new('Point');
$g->SetPoint(1, 2);
$f->SetGeomField($g);
$layer->CreateFeature($f);
This is an example of reading a vector dataset.
use Geo::GDAL::FFI qw/Open/;
my $layer = Open('test.shp')->GetLayer;
$layer->ResetReading;
while (my $feature = $layer->GetNextFeature) {
my $value = $feature->GetField('name');
my $geom = $feature->GetGeomField;
say $value, ' ', $geom->AsText;
}
This is an example of creating a raster dataset.
use Geo::GDAL::FFI qw/GetDriver/;
my $tiff = GetDriver('GTiff')->Create('test.tiff', 3, 2);
my $ogc_wkt =
'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,'.
'AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,'.
'AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,'.
'AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]';
$tiff->SetProjectionString($ogc_wkt);
my $transform = [10,2,0,20,0,3];
$tiff->SetGeoTransform($transform);
my $data = [[0,1,2],[3,4,5]];
$tiff->GetBand->Write($data);
This is an example of reading a raster dataset. Note that using L
and L can greatly reduce the time needed to process large
raster datasets.
use Geo::GDAL::FFI qw/Open/;
my $band = Open($ARGV[0])->GetBand;
my ($w_band, $h_band) = $band->GetSize;
my ($w_block, $h_block) = $band->GetBlockSize;
my $nodata = $band->GetNoDataValue;
my ($xoff, $yoff) = (0,0);
my ($min, $max);
while (1) {
if ($xoff >= $w_band) {
$xoff = 0;
$yoff += $h_block;
last if $yoff >= $h_band;
}
my $w_real = $w_band - $xoff;
$w_real = $w_block if $w_real > $w_block;
my $h_real = $h_band - $yoff;
$h_real = $h_block if $h_real > $h_block;
my $data = $band->Read($xoff, $yoff, $w_real, $h_real);
for my $y (0..$#$data) {
my $row = $data->[$y];
for my $x (0..$#$row) {
my $value = $row->[$x];
next if defined $nodata && $value == $nodata;
$min = $value if !defined $min || $value < $min;
$max = $value if !defined $max || $value > $max;
}
}
$xoff += $w_block;
}
say "min = $min, max = $max";
=head1 DESCRIPTION
This is a foreign function interface to the GDAL geospatial data
access library.
=head1 IMPORTABLE FUNCTIONS
The most important importable functions are GetDriver and Open, which
return a driver and a dataset objects respectively. GetDrivers returns
all available drivers as objects.
Other importable functions include error handling configuration
(SetErrorHandling and UnsetErrorHandling), functions that return lists
of strings that are used in methods (Capabilities, OpenFlags,
DataTypes, ResamplingMethods, FieldTypes, FieldSubtypes,
Justifications, ColorInterpretations, GeometryTypes, GeometryFormats,
GridAlgorithms), also functions GetVersionInfo, HaveGEOS,
SetConfigOption, GetConfigOption, FindFile, PushFinderLocation,
PopFinderLocation, and FinderClean can be imported.
:all imports all above functions.
=head2 GetVersionInfo
my $info = GetVersionInfo($request);
Returns the version information from the underlying GDAL
library. $request is optional and by default 'VERSION_NUM'.
=head2 GetDriver
my $driver = GetDriver($name);
Returns the specific driver object.
=head2 GetDrivers
Returns a list of all available driver objects.
=head2 Open
my $dataset = Open($name, {Flags => [qw/READONLY/], ...});
Open a dataset. $name is the name of the dataset. Named arguments are
the following.
=over 4
=item C
Optional, default is a reference to an empty array. Note that some
drivers can open both raster and vector datasets.
=item C
Optional, default is all drivers. Use a reference to an array of
driver names to limit which drivers to test.
=item C
Optional, default is to probe the file system. You may use a reference
to an array of auxiliary file names.
=item C
Optional, a reference to an array of driver specific open
options. Consult the main GDAL documentation for open options.
=back
=head2 Capabilities
Returns the list of capabilities (strings) a GDAL major object
(Driver, Dataset, Band, or Layer in Geo::GDAL::FFI) can have.
=head2 OpenFlags
Returns the list of opening flags to be used in the Open method.
=head2 DataTypes
Returns the list of raster cell data types to be used in e.g. the
CreateDataset method of the Driver class.
=head2 FieldTypes
Returns the list of field types.
=head2 FieldSubtypes
Returns the list of field subtypes.
=head2 Justifications
Returns the list of field justifications.
=head2 ColorInterpretations
Returns the list of color interpretations.
=head2 GeometryTypes
Returns the list of geometry types.
=head2 SetErrorHandling
Set a Perl function to catch errors reported within GDAL with
CPLError. The errors are collected into @Geo::GDAL::FFI::errors and
confessed if a method fails. This is the default.
=head2 UnsetErrorHandling
Unset the Perl function to catch GDAL errors. If no other error
handler is set, GDAL prints the errors into stderr.
=head1 NOTES ABOUT THREAD-SAFETY
This module is thread-safe provided the error handling is taken care of.
To ensure thread-safety GDAL error handling is automatically disabled
before creating a new thread and re-enabled after that in the just
created thread. The main thread needs to re-enable it via C,
after all thread creations and before eventually using any GDAL function. This
must be done explicitly in the main thread because there is no way
to do that automatically as for other threads.
=head1 METHODS
=head2 get_instance
my $gdal = Geo::GDAL::FFI->get_instance;
Obtain the Geo::GDAL::FFI singleton object. The object is usually not needed.
=head1 LICENSE
This software is released under the Artistic License. See
L.
=head1 AUTHOR
Ari Jolma - Ari.Jolma at gmail.com
=head1 SEE ALSO
L
L
L
L
L
L
L
L
L
L
L
L
L
L, L, L
=cut
__END__;
Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/ 0000755 0001755 0001755 00000000000 15201444175 014705 5 ustar pause pause Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/VSI.pm 0000644 0001755 0001755 00000004464 15201437455 015717 0 ustar pause pause package Geo::GDAL::FFI::VSI;
use v5.10;
use strict;
use warnings;
use Encode qw(decode encode);
use Carp;
use FFI::Platypus::Buffer;
require Exporter;
our $VERSION = '0.16';
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(Mkdir Rmdir ReadDir FOpen Unlink Rename);
sub FOpen {
return Geo::GDAL::FFI::VSI::File->Open(@_);
}
sub Unlink {
my ($path) = @_;
my $e = Geo::GDAL::FFI::VSIUnlink(encode(utf8 => $path));
confess Geo::GDAL::FFI::error_msg() // "Failed to unlink '$path'." if $e == -1;
}
sub Rename {
my ($path, $new_path) = @_;
my $e = Geo::GDAL::FFI::VSIRename(encode(utf8 => $path), encode(utf8 => $new_path));
confess Geo::GDAL::FFI::error_msg() // "Failed to rename '$path' to '$new_path'." if $e == -1;
}
sub Mkdir {
my ($path, $mode) = @_;
$mode //= hex '0x0666';
my $e = Geo::GDAL::FFI::VSIMkdir(encode(utf8 => $path), $mode);
confess Geo::GDAL::FFI::error_msg() // "Failed to mkdir '$path'." if $e == -1;
}
sub Rmdir {
my ($path) = @_;
my $e = Geo::GDAL::FFI::VSIRmdir(encode(utf8 => $path));
confess Geo::GDAL::FFI::error_msg() // "Failed to rmdir '$path'." if $e == -1;
}
sub ReadDir {
my ($path, $max_files) = @_;
$max_files //= 0;
my $csl = Geo::GDAL::FFI::VSIReadDirEx(encode(utf8 => $path), $max_files);
my @dir;
for my $i (0 .. Geo::GDAL::FFI::CSLCount($csl)-1) {
push @dir, decode utf8 => Geo::GDAL::FFI::CSLGetField($csl, $i);
}
Geo::GDAL::FFI::CSLDestroy($csl);
return @dir;
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI::VSI - A GDAL virtual file system
=head1 SYNOPSIS
use Geo::GDAL::FFI::VSI qw/FOpen Mkdir ReadDir/;
=head1 DESCRIPTION
=head1 METHODS
=head2 FOpen($path, $access)
my $file = FOpen('/vsimem/file', 'w');
Short for Geo::GDAL::FFI::VSI::File::Open
=head2 Mkdir($path, $mode)
$mode is optional and by default 0x0666.
=head2 ReadDir($path, $max_files)
$max_files is optional and by default 0, i.e., read all names of files
in the dir.
=head1 LICENSE
This software is released under the Artistic License. See
L.
=head1 AUTHOR
Ari Jolma - Ari.Jolma at gmail.com
=head1 SEE ALSO
L
L, L, L
=cut
__END__;
Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/VSI/ 0000755 0001755 0001755 00000000000 15201444175 015346 5 ustar pause pause Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/VSI/File.pm 0000644 0001755 0001755 00000004720 15201437455 016571 0 ustar pause pause package Geo::GDAL::FFI::VSI::File;
use v5.10;
use strict;
use warnings;
use Encode qw(decode encode);
use Carp;
use FFI::Platypus::Buffer;
our $VERSION = '0.16';
sub Open {
my ($class, $path, $access) = @_;
$access //= 'r';
my $self = {};
$self->{handle} = Geo::GDAL::FFI::VSIFOpenExL(encode(utf8 => $path), $access, 1);
unless ($self->{handle}) {
confess Geo::GDAL::FFI::error_msg() // "Failed to open '$path' with access '$access'.";
}
return bless $self, $class;
}
sub DESTROY {
my ($self) = @_;
$self->Close;
}
sub Close {
my ($self) = @_;
return unless $self->{handle};
my $e = Geo::GDAL::FFI::VSIFCloseL($self->{handle});
confess Geo::GDAL::FFI::error_msg() // "Failed to close a VSIFILE." if $e == -1;
delete $self->{handle};
}
sub Read {
my ($self, $len) = @_;
$len //= 1;
my $buf = ' ' x $len;
my ($pointer, $size) = scalar_to_buffer $buf;
my $n = Geo::GDAL::FFI::VSIFReadL($pointer, 1, $len, $self->{handle});
return substr $buf, 0, $n;
}
sub Write {
my ($self, $buf) = @_;
my $len = do {use bytes; length($buf)};
my $ffi = FFI::Platypus->new();
my $address = $ffi->cast('string' => 'opaque', $buf);
return Geo::GDAL::FFI::VSIFWriteL($address, 1, $len, $self->{handle});
}
sub Ingest {
my ($self) = @_;
my $s;
my $e = Geo::GDAL::FFI::VSIIngestFile($self->{handle}, '', \$s, 0, -1);
return $s;
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI::VSI::File - A GDAL virtual file
=head1 SYNOPSIS
=head1 DESCRIPTION
=head1 METHODS
=head2 Open
my $vsifile = Geo::GDAL::FFI::VSI::File->Open($name, $access);
Open a virtual file. $name is the name of the file to open. $access is
'r', 'r+', 'a', or 'w'. 'r' is the default.
Returns a Geo::GDAL::FFI::VSI::File object.
=head2 Close
Closes the file handle. Is done automatically when the object is
destroyed.
=head2 Read($len)
Read $len bytes from the file. Returns the bytes in a Perl
string. $len is optional and by default 1.
=head2 Write($buf)
Write the Perl string $buf into the file. Returns the number of
successfully written bytes.
=head1 LICENSE
This software is released under the Artistic License. See
L.
=head1 AUTHOR
Ari Jolma - Ari.Jolma at gmail.com
=head1 SEE ALSO
L
L, L, L
=cut
__END__;
Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/SpatialReference.pm 0000644 0001755 0001755 00000007167 15201437455 020475 0 ustar pause pause package Geo::GDAL::FFI::SpatialReference;
use v5.10;
use strict;
use warnings;
use Carp;
our $VERSION = '0.16';
sub new {
my ($class, $arg, @arg) = @_;
my $sr;
if (not defined $arg) {
$sr = Geo::GDAL::FFI::OSRNewSpatialReference();
} elsif (not @arg) {
$sr = Geo::GDAL::FFI::OSRNewSpatialReference($arg);
} else {
$sr = Geo::GDAL::FFI::OSRNewSpatialReference();
my $gdal = Geo::GDAL::FFI->get_instance;
$arg = $gdal->get_importer($arg);
if ($arg->($sr, @arg) != 0) {
Geo::GDAL::FFI::OSRDestroySpatialReference($sr);
$sr = 0;
}
}
return bless \$sr, $class if $sr;
confess Geo::GDAL::FFI::error_msg();
}
sub DESTROY {
my $self = shift;
# OSRGetReferenceCount method not yet implemented
my $refcount = (Geo::GDAL::FFI::OSRReference ($$self)-1);
Geo::GDAL::FFI::OSRDereference ($$self); # immediately decrement
if ($refcount == 0) {
#warn "Calling DESTROY method for $$self\n";
Geo::GDAL::FFI::OSRDestroySpatialReference($$self);
}
}
sub Export {
my $self = shift;
my $format = shift;
my $gdal = Geo::GDAL::FFI->get_instance;
my $exporter = $gdal->get_exporter($format);
my $x;
if ($exporter->($$self, \$x, @_) != 0) {
confess Geo::GDAL::FFI::error_msg();
}
return $x;
}
sub Set {
my $self = shift;
my $set = shift;
my $gdal = Geo::GDAL::FFI->get_instance;
my $setter = $gdal->get_setter($set);
if ($setter->($$self, @_) != 0) {
confess Geo::GDAL::FFI::error_msg();
}
}
sub Clone {
my $self = shift;
my $s = Geo::GDAL::FFI::OSRClone($$self);
return bless \$s, 'Geo::GDAL::FFI::SpatialReference';
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI::SpatialReference - A spatial reference system in GDAL
=head1 SYNOPSIS
=head1 DESCRIPTION
=head1 METHODS
=head2 new
Create a new SpatialReference object.
my $sr = Geo::GDAL::FFI::SpatialReference->new('WKT here...');
If only one argument is given, it is taken as the well known text
(WKT) associated with the spatial reference system (SRS).
my $sr = Geo::GDAL::FFI::SpatialReference->new(EPSG => 3067);
If there are more than one argument, the first argument is taken as a
format and the rest of the arguments are taken as arguments to the
format. The list of formats known to GDAL (at the time of this
writing) is EPSG, EPSGA, Wkt, Proj4, ESRI, PCI, USGS, XML, Dict,
Panorama, Ozi, MICoordSys, ERM, Url.
=head2 Export
$sr->Export($format, @args);
Export a SpatialReference object to a format. The list of formats
known to GDAL (at the time of this writing) is Wkt, PrettyWkt, Proj4,
PCI, USGS, XML, Panorama, MICoordSys, ERM.
=head2 Set
$sr->Set($proj, @args);
Set projection parameters in a SpatialReference object. The list of
projection parameters known to GDAL (at the time of this writing) is
Axes, ACEA, AE, Bonne, CEA, CS, EC, Eckert, EckertIV, EckertVI,
Equirectangular, Equirectangular2, GS, GH, IGH, GEOS,
GaussSchreiberTMercator, Gnomonic, HOM, HOMAC, HOM2PNO, IWMPolyconic,
Krovak, LAEA, LCC, LCC1SP, LCCB, MC, Mercator, Mercator2SP, Mollweide,
NZMG, OS, Orthographic, Polyconic, PS, Robinson, Sinusoidal,
Stereographic, SOC, TM, TMVariant, TMG, TMSO, TPED, VDG, Wagner, QSC,
SCH.
=head1 LICENSE
This software is released under the Artistic License. See
L.
=head1 AUTHOR
Ari Jolma - Ari.Jolma at gmail.com
=head1 SEE ALSO
L
L, L, L
=cut
__END__;
Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/Object.pm 0000644 0001755 0001755 00000010316 15201437455 016455 0 ustar pause pause package Geo::GDAL::FFI::Object;
use v5.10;
use strict;
use warnings;
use Carp;
our $VERSION = '0.16';
sub GetDescription {
my $self = shift;
return Geo::GDAL::FFI::GDALGetDescription($$self);
}
sub HasCapability {
my ($self, $cap) = @_;
my $tmp = $Geo::GDAL::FFI::capabilities{$cap};
confess "Unknown capability: $cap." unless defined $tmp;
my $md = $self->GetMetadata('');
return $md->{'DCAP_'.$cap};
}
sub GetMetadataDomainList {
my ($self) = @_;
my $csl = Geo::GDAL::FFI::GDALGetMetadataDomainList($$self);
my @list;
for my $i (0..Geo::GDAL::FFI::CSLCount($csl)-1) {
push @list, Geo::GDAL::FFI::CSLGetField($csl, $i);
}
Geo::GDAL::FFI::CSLDestroy($csl);
return wantarray ? @list : \@list;
}
sub GetMetadata {
my ($self, $domain) = @_;
my %md;
unless (defined $domain) {
for $domain ($self->GetMetadataDomainList) {
$md{$domain} = $self->GetMetadata($domain);
}
return wantarray ? %md : \%md;
}
my $csl = Geo::GDAL::FFI::GDALGetMetadata($$self, $domain);
for my $i (0..Geo::GDAL::FFI::CSLCount($csl)-1) {
my ($name, $value) = split /=/, Geo::GDAL::FFI::CSLGetField($csl, $i);
$md{$name} = $value;
}
return wantarray ? %md : \%md;
}
sub SetMetadata {
my ($self, $metadata, $domain) = @_;
unless (defined $domain) {
for $domain (keys %$metadata) {
$self->SetMetadata($metadata->{$domain}, $domain);
}
} else {
my $csl = 0;
for my $name (keys %$metadata) {
$csl = Geo::GDAL::FFI::CSLAddString($csl, "$name=$metadata->{$name}");
}
my $err = Geo::GDAL::FFI::GDALSetMetadata($$self, $csl, $domain);
Geo::GDAL::FFI::CSLDestroy($csl);
confess Geo::GDAL::FFI::error_msg() if $err == $Geo::GDAL::FFI::Failure;
warn Geo::GDAL::FFI::error_msg() if $err == $Geo::GDAL::FFI::Warning;
}
}
sub GetMetadataItem {
my ($self, $name, $domain) = @_;
$domain //= "";
return Geo::GDAL::FFI::GDALGetMetadataItem($$self, $name, $domain);
}
sub SetMetadataItem {
my ($self, $name, $value, $domain) = @_;
$domain //= "";
my $err = Geo::GDAL::FFI::GDALSetMetadataItem($$self, $name, $value, $domain);
confess Geo::GDAL::FFI::error_msg() if $err == $Geo::GDAL::FFI::Failure;
warn Geo::GDAL::FFI::error_msg() if $err == $Geo::GDAL::FFI::Warning;
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI::Object - A GDAL major object
=head1 SYNOPSIS
=head1 DESCRIPTION
The base class for classes Driver, Dataset, Band, and Layer.
=head1 METHODS
=head2 GetDescription
my $desc = $object->GetDescription;
=head2 HasCapability
my $has_cap = $object->HasCapability($capability);
=head2 GetMetadataDomainList
my @domains = $object->GetMetadataDomainList;
=head2 GetMetadata
my %metadata = $object->GetMetadata($domain);
Returns the object metadata of a given domain.
my $metadata = $object->GetMetadata($domain);
Returns the object metadata of a given domain in an anonymous hash.
my %metadata = $object->GetMetadata;
Returns the object metadata.
my $metadata = $object->GetMetadata;
Returns the object metadata in an anonymous hash.
=head2 SetMetadata
$object->SetMetadata($metadata, $domain);
Sets the object metadata in a given domain. The metadata is in an
anonymous hash.
$object->SetMetadata($metadata);
Sets the object metadata in the domains that are the keys of the hash
$metadata references. The values of the hash are the metadata in
anonymous hashes.
=head2 GetMetadataItem
my $value = $object->GetMetadataItem($item, $domain)
Gets the value of the metadata item in a domain (by default an empty
string).
=head2 SetMetadataItem
$object->GetMetadataItem($item, $value, $domain)
Sets the value of the metadata item in a domain (by default an empty
string).
=head1 LICENSE
This software is released under the Artistic License. See
L.
=head1 AUTHOR
Ari Jolma - Ari.Jolma at gmail.com
=head1 SEE ALSO
L
L, L, L
=cut
__END__;
Geo-GDAL-FFI-0.16/lib/Geo/GDAL/FFI/Layer.pm 0000644 0001755 0001755 00000015743 15201437455 016334 0 ustar pause pause package Geo::GDAL::FFI::Layer;
use v5.10;
use strict;
use warnings;
use Carp;
use base 'Geo::GDAL::FFI::Object';
our $VERSION = '0.16';
sub DESTROY {
my $self = shift;
Geo::GDAL::FFI::OGR_L_SyncToDisk($$self);
#say STDERR "delete parent $parent{$$self}";
Geo::GDAL::FFI::_deregister_parent_ref ($$self);
#say STDERR "destroy $self";
}
sub GetParentDataset {
my ($self) = @_;
return Geo::GDAL::FFI::_get_parent_ref ($$self);
}
sub GetDefn {
my $self = shift;
my $d = Geo::GDAL::FFI::OGR_L_GetLayerDefn($$self);
return bless \$d, 'Geo::GDAL::FFI::FeatureDefn';
}
sub CreateField {
my $self = shift;
my $def = shift;
unless (ref $def) {
# name => type calling syntax
my $name = $def;
my $type = shift;
$def = Geo::GDAL::FFI::FieldDefn->new({Name => $name, Type => $type})
} elsif (ref $def eq 'HASH') {
$def = Geo::GDAL::FFI::FieldDefn->new($def)
}
my $approx_ok = shift // 1;
my $e = Geo::GDAL::FFI::OGR_L_CreateField($$self, $$def, $approx_ok);
return unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
sub CreateGeomField {
my $self = shift;
my $def = shift;
unless (ref $def) {
# name => type calling syntax
my $name = $def;
my $type = shift;
$def = Geo::GDAL::FFI::GeomFieldDefn->new({Name => $name, Type => $type});
} elsif (ref $def eq 'HASH') {
$def = Geo::GDAL::FFI::GeomFieldDefn->new($def)
}
my $approx_ok = shift // 1;
my $e = Geo::GDAL::FFI::OGR_L_CreateGeomField($$self, $$def, $approx_ok);
return unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
sub GetSpatialRef {
my ($self) = @_;
my $sr = Geo::GDAL::FFI::OGR_L_GetSpatialRef($$self);
return unless $sr;
return bless \$sr, 'Geo::GDAL::FFI::SpatialReference';
}
sub ResetReading {
my $self = shift;
Geo::GDAL::FFI::OGR_L_ResetReading($$self);
}
sub GetNextFeature {
my $self = shift;
my $f = Geo::GDAL::FFI::OGR_L_GetNextFeature($$self);
return unless $f;
return bless \$f, 'Geo::GDAL::FFI::Feature';
}
sub GetFeature {
my ($self, $fid) = @_;
my $f = Geo::GDAL::FFI::OGR_L_GetFeature($$self, $fid);
confess unless $f;
return bless \$f, 'Geo::GDAL::FFI::Feature';
}
sub GetFeatureCount {
my ($self, $force) = @_;
Geo::GDAL::FFI::OGR_L_GetFeatureCount($$self, !!$force);
}
sub SetFeature {
my ($self, $f) = @_;
Geo::GDAL::FFI::OGR_L_SetFeature($$self, $$f);
}
sub CreateFeature {
my ($self, $f) = @_;
my $e = Geo::GDAL::FFI::OGR_L_CreateFeature($$self, $$f);
return $f unless $e;
}
sub DeleteFeature {
my ($self, $fid) = @_;
my $e = Geo::GDAL::FFI::OGR_L_DeleteFeature($$self, $fid);
return unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
__PACKAGE__->_make_overlay_methods();
sub _make_overlay_methods {
my ($pkg) = @_;
my @methods = (qw /
Intersection Union SymDifference
Identity Update Clip Erase
/);
no strict 'refs';
foreach my $method_name (@methods) {
*{$pkg . '::' . $method_name} =
sub {
my ($self, $method, $args) = @_;
confess "Method layer missing." unless $method;
$args //= {};
my $result = $args->{Result};
unless ($result) {
my $schema = {
GeometryType => 'Unknown'
};
state $mem_driver = Geo::GDAL::FFI::get_memory_driver();
$result = Geo::GDAL::FFI::GetDriver($mem_driver)->Create->CreateLayer($schema);
}
my $o = 0;
for my $key (keys %{$args->{Options}}) {
$o = Geo::GDAL::FFI::CSLAddString($o, "$key=$args->{Options}{$key}");
}
my $p = 0;
$p = FFI::Platypus->new->closure($args->{Progress}) if $args->{Progress};
my $e = &{'Geo::GDAL::FFI::OGR_L_'.$method_name} ($$self, $$method, $$result, $o, $p, $args->{ProgressData});
Geo::GDAL::FFI::CSLDestroy($o);
return $result unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
};
}
return;
}
sub GetExtent {
my ($self, $force) = @_;
my $extent = [0,0,0,0];
$force = $force ? \1 : \0; # ensure $force is a ref
my $e = Geo::GDAL::FFI::OGR_L_GetExtent ($$self, $extent, $force);
return $extent unless $e;
confess Geo::GDAL::FFI::error_msg({OGRError => $e});
}
sub GetName {
my ($self) = @_;
return $self->GetDefn->GetName;
}
1;
=pod
=encoding UTF-8
=head1 NAME
Geo::GDAL::FFI::Layer - A collection of vector features in GDAL
=head1 SYNOPSIS
=head1 DESCRIPTION
A set of (vector) features having a same schema (the same Defn
object). Obtain a layer object by the CreateLayer or GetLayer method
of a vector dataset object.
Note that the system stores a reference to the parent dataset for
each layer object to ensure layer objects remain viable.
If you are relying on a dataset object's destruction to
flush its dataset cache and then close it then you need to ensure
all associated child layers are also destroyed. Failure to do so could
lead to corrupt data when reading in newly written files.
=head1 METHODS
=head2 GetDefn
my $defn = $layer->GetDefn;
Returns the FeatureDefn object for this layer.
=head2 ResetReading
$layer->ResetReading;
=head2 GetNextFeature
my $feature = $layer->GetNextFeature;
=head2 GetFeature
my $feature = $layer->GetFeature($fid);
=head2 SetFeature
$layer->SetFeature($feature);
=head2 CreateFeature
$layer->CreateFeature($feature);
=head2 DeleteFeature
$layer->DeleteFeature($fid);
=head2 GetFeatureCount
my $count = $layer->GetFeatureCount();
=head2 GetExtent
$layer->GetExtent();
$layer->GetExtent(1);
Returns an array ref with [minx, miny, maxx, maxy].
Argument is a boolean to force calculation even
if it is expensive.
=head2 Intersection, Union, SymDifference, Identity, Update, Clip, Erase
$result = $layer->($method, $args);
Runs the algorithm between layer and method layer. Named
arguments are the following.
=over 4
=item C
Optional, allows the user to define the result layer.
=item C
Optional, allows the user to define the options (see GDAL docs).
=item C