From d130384defdd4eda916793711691890dd9283bc5 Mon Sep 17 00:00:00 2001 From: Francesco Paolo Lovergine Date: Tue, 21 Nov 2023 12:45:36 +0100 Subject: [PATCH 01/18] Changed string_pointer into standard string* and changed new() to be thread-safe. Added a t/threads.t test to verify that multi-threading does not crash. --- build-tools/parse_h.pl | 4 +-- lib/Geo/GDAL/FFI.pm | 66 ++++++++++++++++++++++-------------------- t/threads.t | 61 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 34 deletions(-) create mode 100644 t/threads.t diff --git a/build-tools/parse_h.pl b/build-tools/parse_h.pl index c493c96..900957a 100644 --- a/build-tools/parse_h.pl +++ b/build-tools/parse_h.pl @@ -382,8 +382,8 @@ sub parse_type { $arg = 'opaque'; } else { my $ok = $char_p_p_ok{$name} || $char_p_p_ok{$name.'.'.$var}; - say STDERR "WARNING: char ** in $name ($mode, $var) defaulting to string_pointer" unless $ok; - $arg = 'string_pointer'; + say STDERR "$name returns a string*" unless $ok; + $arg = 'string*'; } } elsif ($arg =~ /char\s*\*/) { if ($mode eq 'ret' && $use_ret_opaque{$name}) { diff --git a/lib/Geo/GDAL/FFI.pm b/lib/Geo/GDAL/FFI.pm index 55bb80e..8116756 100644 --- a/lib/Geo/GDAL/FFI.pm +++ b/lib/Geo/GDAL/FFI.pm @@ -85,12 +85,14 @@ sub SetErrorHandling { 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}; } @@ -436,7 +438,6 @@ sub new { return $instance if $instance; my $ffi = FFI::Platypus->new; - $ffi->load_custom_type('::StringPointer' => 'string_pointer'); my @libs = $gdal->dynamic_libs; $ffi->lib(@libs); @@ -460,13 +461,14 @@ sub new { $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_pointer uint64* sint64/] => 'int'); + $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'); @@ -560,7 +562,7 @@ $ffi->attach('GDALDatasetRasterIO' => ['opaque','unsigned 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_pointer/] => 'int'); +$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'); @@ -609,14 +611,14 @@ $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_pointer/] => 'bool'); -$ffi->attach('GDALDatasetDeleteFieldDomain' => [qw/opaque string string_pointer/] => 'bool'); -$ffi->attach('GDALDatasetUpdateFieldDomain' => [qw/opaque opaque string_pointer/] => 'bool'); +$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_pointer/] => 'bool'); -$ffi->attach('GDALDatasetDeleteRelationship' => [qw/opaque string string_pointer/] => 'bool'); -$ffi->attach('GDALDatasetUpdateRelationship' => [qw/opaque opaque string_pointer/] => 'bool'); +$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'); @@ -685,7 +687,7 @@ $ffi->attach('GDALGetDataCoverageStatus' => [qw/opaque int int int int int doubl $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_pointer int/] => 'int'); +$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'); @@ -695,10 +697,10 @@ $ffi->attach('GDALDeinterleave' => ['opaque','unsigned int','int','opaque','unsi $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_pointer int* opaque/] => 'int'); -$ffi->attach('GDALReadTabFile' => [qw/string double* string_pointer int* opaque/] => 'int'); -$ffi->attach('GDALLoadOziMapFile' => [qw/string double* string_pointer int* opaque/] => 'int'); -$ffi->attach('GDALReadOziMapFile' => [qw/string double* string_pointer int* opaque/] => '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'); @@ -911,7 +913,7 @@ $ffi->attach('GDALDimensionSetIndexingVariable' => [qw/opaque opaque/] => 'int') $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_pointer opaque uint64*/] => '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'); @@ -939,9 +941,9 @@ $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_pointer/] => 'int'); -$ffi->attach('OGR_G_ExportToWkt' => [qw/opaque string_pointer/] => 'int'); -$ffi->attach('OGR_G_ExportToIsoWkt' => [qw/opaque string_pointer/] => 'int'); +$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'); @@ -1348,7 +1350,7 @@ $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_pointer/] => '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'); @@ -1360,16 +1362,16 @@ $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_pointer/] => 'int'); -$ffi->attach('OSRExportToWktEx' => [qw/opaque string_pointer opaque/] => 'int'); -$ffi->attach('OSRExportToPrettyWkt' => [qw/opaque string_pointer int/] => 'int'); -$ffi->attach('OSRExportToPROJJSON' => [qw/opaque string_pointer opaque/] => 'int'); -$ffi->attach('OSRExportToProj4' => [qw/opaque string_pointer/] => 'int'); -$ffi->attach('OSRExportToPCI' => [qw/opaque string_pointer string_pointer double*/] => '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_pointer string/] => '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_pointer/] => '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'); @@ -1379,13 +1381,13 @@ $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_pointer/] => 'double'); +$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_pointer/] => 'double'); -$ffi->attach('OSRGetTargetLinearUnits' => [qw/opaque string string_pointer/] => 'double'); -$ffi->attach('OSRGetPrimeMeridian' => [qw/opaque string_pointer/] => 'double'); +$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'); @@ -1598,7 +1600,7 @@ $ffi->attach('GDALVectorInfo' => [qw/opaque opaque/] => 'string'); $instance = {}; $instance->{ffi} = $ffi; $instance->{gdal} = $gdal; - SetErrorHandling(); + #SetErrorHandling(); GDALAllRegister(); return bless $instance, $class; } diff --git a/t/threads.t b/t/threads.t new file mode 100644 index 0000000..a1b4336 --- /dev/null +++ b/t/threads.t @@ -0,0 +1,61 @@ +use v5.18; +use threads; +use threads::shared; +use warnings; +use strict; +use Test::More; + +BEGIN { use_ok('Geo::GDAL::FFI', qw/:all/); } + +use 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 { + my $gdal = Geo::GDAL::FFI->get_instance; + $gdal->SetErrorHandling; + 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 $gdal = Geo::GDAL::FFI->get_instance; + $gdal->SetErrorHandling; + my $v = rand(100); + say "thread in$i: pushed $v"; + $q->enqueue({ value => $v }); + } + ); + push @in_thrds, $t; +} + +my $gdal = Geo::GDAL::FFI->get_instance; +$gdal->SetErrorHandling; + +# 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(); From 52559f55b3dcc99b696daf8f3a3eaa523ac4678e Mon Sep 17 00:00:00 2001 From: Francesco Paolo Lovergine Date: Tue, 21 Nov 2023 14:09:52 +0100 Subject: [PATCH 02/18] Changed t/threads.t to skip when ithreads are not implemented --- t/threads.t | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/t/threads.t b/t/threads.t index a1b4336..d7ea017 100644 --- a/t/threads.t +++ b/t/threads.t @@ -1,13 +1,20 @@ use v5.18; -use threads; -use threads::shared; use warnings; use strict; +use Config; use Test::More; -BEGIN { use_ok('Geo::GDAL::FFI', qw/:all/); } +BEGIN { + use_ok('Geo::GDAL::FFI', qw/:all/); +} + +SKIP: { + +skip "skip multi-thread test", 4 unless $Config{useithreads}; -use Thread::Queue; +use_ok('threads'); +use_ok('threads::shared'); +use_ok('Thread::Queue'); my $q = Thread::Queue->new(); my @in_thrds = (); @@ -58,4 +65,7 @@ for my $w (@out_thrds) { ok(1, "threading seems ok"); +} + + done_testing(); From 5660700f5d8a2558a2d5f2e2942093e82fd3488c Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Sat, 18 Nov 2023 12:07:21 +1100 Subject: [PATCH 03/18] vsistdout.t: write method needs to return 1 Also generate two features to ensure the write works properly. Otherwise a single feature was being written but followed by a failure. --- t/vsistdout.t | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/t/vsistdout.t b/t/vsistdout.t index 02be848..61ff542 100644 --- a/t/vsistdout.t +++ b/t/vsistdout.t @@ -19,9 +19,10 @@ use JSON; sub write { my $line = shift; push @output, $line; + return 1; } sub close { - push @output, "end"; + return 1; } sub output { my $output = join '', @output; @@ -33,14 +34,17 @@ use JSON; # test vsistdout redirection if(1){ # create a small layer and copy it to vsistdout with redirection - my $layer = GetDriver('Memory')->Create->CreateLayer({GeometryType => 'None'}); + my $ds = GetDriver('Memory')->Create; + my $layer = $ds->CreateLayer({GeometryType => 'None'}); $layer->CreateField(value => 'Integer'); $layer->CreateGeomField(geom => 'Point'); - my $feature = Geo::GDAL::FFI::Feature->new($layer->GetDefn); - $feature->SetField(value => 12); - $feature->SetGeomField(geom => [WKT => 'POINT(1 1)']); - $layer->CreateFeature($feature); - + 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); @@ -48,16 +52,18 @@ if(1){ $gdal->CloseWriter; my $ret = $output->output; - ok($ret eq - '{"type": "FeatureCollection",'. - '"features": '. - '[{ "type": "Feature", "id": 0, "properties": '. - '{ "value": 12 }, "geometry": { "type": "Point", '. - '"coordinates": [ 1.0, 1.0 ] } }]}end', + my $exp = <<'EODATA' +{"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 ] } }]} +EODATA + ; + $exp =~ s/\n$//; + + is($ret, $exp, "Redirect vsistdout to write/close methods of a class."); } + # test Translate if(1){ my $ds = GetDriver('GTiff')->Create('/vsimem/test.tiff', 10); From 20325bbca5d98c137d96eaf1295535595b8c0f71 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Sat, 18 Nov 2023 12:22:03 +1100 Subject: [PATCH 04/18] t/vsistdout.t: decode JSON and use is_deeply for test Refactor the expected structure in the process. --- t/vsistdout.t | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/t/vsistdout.t b/t/vsistdout.t index 61ff542..8159f92 100644 --- a/t/vsistdout.t +++ b/t/vsistdout.t @@ -52,13 +52,11 @@ if(1){ $gdal->CloseWriter; my $ret = $output->output; - my $exp = <<'EODATA' -{"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 ] } }]} -EODATA - ; - $exp =~ s/\n$//; + $ret = decode_json $ret; - is($ret, $exp, + my $exp = decode_json (get_expected_json_data()); + + is_deeply ($ret, $exp, "Redirect vsistdout to write/close methods of a class."); } @@ -72,3 +70,38 @@ if(1){ } 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; +} + + From 99ce608b9944d77fef5f17d16f23a770013895f8 Mon Sep 17 00:00:00 2001 From: Ari Jolma Date: Tue, 19 Dec 2023 07:27:00 +0200 Subject: [PATCH 05/18] Release version 0.11 --- Changes | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Changes b/Changes index 93bf026..41eda02 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,11 @@ Revision history for Perl extension Geo::GDAL::FFI -0.11 unreleased +0.12 unreleased + +0.11 December 19, 2023 - Removed use of to FFI::Platypus::Declare, now discouraged. + - Add Layer::GetFeatureCount method + - Bugfixes 0.10 July 10, 2023 - Add dependency to FFI::Platypus::Declare From 889a34cc62d3f04937b892a1d53b0be21a85cd8b Mon Sep 17 00:00:00 2001 From: Ari Jolma Date: Tue, 19 Dec 2023 07:32:08 +0200 Subject: [PATCH 06/18] Set version to 0.12 --- lib/Geo/GDAL/FFI.pm | 2 +- lib/Geo/GDAL/FFI/Band.pm | 2 +- lib/Geo/GDAL/FFI/Dataset.pm | 2 +- lib/Geo/GDAL/FFI/Driver.pm | 2 +- lib/Geo/GDAL/FFI/Feature.pm | 2 +- lib/Geo/GDAL/FFI/FeatureDefn.pm | 2 +- lib/Geo/GDAL/FFI/FieldDefn.pm | 2 +- lib/Geo/GDAL/FFI/GeomFieldDefn.pm | 2 +- lib/Geo/GDAL/FFI/Geometry.pm | 2 +- lib/Geo/GDAL/FFI/Layer.pm | 2 +- lib/Geo/GDAL/FFI/Object.pm | 2 +- lib/Geo/GDAL/FFI/SpatialReference.pm | 2 +- lib/Geo/GDAL/FFI/VSI.pm | 2 +- lib/Geo/GDAL/FFI/VSI/File.pm | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/Geo/GDAL/FFI.pm b/lib/Geo/GDAL/FFI.pm index 8116756..cb62ae4 100644 --- a/lib/Geo/GDAL/FFI.pm +++ b/lib/Geo/GDAL/FFI.pm @@ -26,7 +26,7 @@ use Geo::GDAL::FFI::GeomFieldDefn; use Geo::GDAL::FFI::Feature; use Geo::GDAL::FFI::Geometry; -our $VERSION = 0.1100; +our $VERSION = 0.1200; our $DEBUG = 0; our @ISA = qw(Exporter); diff --git a/lib/Geo/GDAL/FFI/Band.pm b/lib/Geo/GDAL/FFI/Band.pm index a95bf8f..0297d9b 100644 --- a/lib/Geo/GDAL/FFI/Band.pm +++ b/lib/Geo/GDAL/FFI/Band.pm @@ -6,7 +6,7 @@ use Carp; use FFI::Platypus::Buffer; use base 'Geo::GDAL::FFI::Object'; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub DESTROY { my $self = shift; diff --git a/lib/Geo/GDAL/FFI/Dataset.pm b/lib/Geo/GDAL/FFI/Dataset.pm index 226aa59..68f9286 100644 --- a/lib/Geo/GDAL/FFI/Dataset.pm +++ b/lib/Geo/GDAL/FFI/Dataset.pm @@ -6,7 +6,7 @@ use Carp; use base 'Geo::GDAL::FFI::Object'; use Scalar::Util qw /blessed/; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub DESTROY { my $self = shift; diff --git a/lib/Geo/GDAL/FFI/Driver.pm b/lib/Geo/GDAL/FFI/Driver.pm index 4900122..3ae7fe0 100644 --- a/lib/Geo/GDAL/FFI/Driver.pm +++ b/lib/Geo/GDAL/FFI/Driver.pm @@ -5,7 +5,7 @@ use warnings; use Carp; use base 'Geo::GDAL::FFI::Object'; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub GetName { my $self = shift; diff --git a/lib/Geo/GDAL/FFI/Feature.pm b/lib/Geo/GDAL/FFI/Feature.pm index ac454af..36b37cd 100644 --- a/lib/Geo/GDAL/FFI/Feature.pm +++ b/lib/Geo/GDAL/FFI/Feature.pm @@ -7,7 +7,7 @@ use Carp; use Encode qw(decode encode); use FFI::Platypus::Buffer; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub new { my ($class, $defn) = @_; diff --git a/lib/Geo/GDAL/FFI/FeatureDefn.pm b/lib/Geo/GDAL/FFI/FeatureDefn.pm index f87ef74..e490465 100644 --- a/lib/Geo/GDAL/FFI/FeatureDefn.pm +++ b/lib/Geo/GDAL/FFI/FeatureDefn.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub new { my ($class, $args) = @_; diff --git a/lib/Geo/GDAL/FFI/FieldDefn.pm b/lib/Geo/GDAL/FFI/FieldDefn.pm index c4fc20b..96e5c5b 100644 --- a/lib/Geo/GDAL/FFI/FieldDefn.pm +++ b/lib/Geo/GDAL/FFI/FieldDefn.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub new { my ($class, $args) = @_; diff --git a/lib/Geo/GDAL/FFI/GeomFieldDefn.pm b/lib/Geo/GDAL/FFI/GeomFieldDefn.pm index d60b459..7eec3be 100644 --- a/lib/Geo/GDAL/FFI/GeomFieldDefn.pm +++ b/lib/Geo/GDAL/FFI/GeomFieldDefn.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub new { my ($class, $args) = @_; diff --git a/lib/Geo/GDAL/FFI/Geometry.pm b/lib/Geo/GDAL/FFI/Geometry.pm index 771b4ac..ce9a455 100644 --- a/lib/Geo/GDAL/FFI/Geometry.pm +++ b/lib/Geo/GDAL/FFI/Geometry.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = 0.1100; +our $VERSION = 0.1200; my %ref; diff --git a/lib/Geo/GDAL/FFI/Layer.pm b/lib/Geo/GDAL/FFI/Layer.pm index aa32613..a37c5ed 100644 --- a/lib/Geo/GDAL/FFI/Layer.pm +++ b/lib/Geo/GDAL/FFI/Layer.pm @@ -5,7 +5,7 @@ use warnings; use Carp; use base 'Geo::GDAL::FFI::Object'; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub DESTROY { my $self = shift; diff --git a/lib/Geo/GDAL/FFI/Object.pm b/lib/Geo/GDAL/FFI/Object.pm index dff9286..a2e8c24 100644 --- a/lib/Geo/GDAL/FFI/Object.pm +++ b/lib/Geo/GDAL/FFI/Object.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub GetDescription { my $self = shift; diff --git a/lib/Geo/GDAL/FFI/SpatialReference.pm b/lib/Geo/GDAL/FFI/SpatialReference.pm index a466627..2bcce4d 100644 --- a/lib/Geo/GDAL/FFI/SpatialReference.pm +++ b/lib/Geo/GDAL/FFI/SpatialReference.pm @@ -4,7 +4,7 @@ use strict; use warnings; use Carp; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub new { my ($class, $arg, @arg) = @_; diff --git a/lib/Geo/GDAL/FFI/VSI.pm b/lib/Geo/GDAL/FFI/VSI.pm index ab6369b..9217bbc 100644 --- a/lib/Geo/GDAL/FFI/VSI.pm +++ b/lib/Geo/GDAL/FFI/VSI.pm @@ -7,7 +7,7 @@ use Carp; use FFI::Platypus::Buffer; require Exporter; -our $VERSION = 0.1100; +our $VERSION = 0.1200; our @ISA = qw(Exporter); our @EXPORT_OK = qw(Mkdir Rmdir ReadDir FOpen Unlink Rename); diff --git a/lib/Geo/GDAL/FFI/VSI/File.pm b/lib/Geo/GDAL/FFI/VSI/File.pm index 7b92c58..6f6982f 100644 --- a/lib/Geo/GDAL/FFI/VSI/File.pm +++ b/lib/Geo/GDAL/FFI/VSI/File.pm @@ -6,7 +6,7 @@ use Encode qw(decode encode); use Carp; use FFI::Platypus::Buffer; -our $VERSION = 0.1100; +our $VERSION = 0.1200; sub Open { my ($class, $path, $access) = @_; From 2453e18bef02d72eba8079560acad9f05e4baae1 Mon Sep 17 00:00:00 2001 From: Francesco Paolo Lovergine Date: Tue, 19 Dec 2023 18:15:41 +0100 Subject: [PATCH 07/18] This branch closes #53 and render Geo::GDAL::FFI thread-safe by disabling GDAL error hanlding before creating new threads and re-enabling in each thread after. No change is required in exisiting code. Just in case of multi-threading the main thread needs to issue a SetErrorHandling() once after creating all required threads just before using GDAL again. --- lib/Geo/GDAL/FFI.pm | 17 ++++++++++++++++- t/threads.t | 8 -------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/lib/Geo/GDAL/FFI.pm b/lib/Geo/GDAL/FFI.pm index cb62ae4..87698d9 100644 --- a/lib/Geo/GDAL/FFI.pm +++ b/lib/Geo/GDAL/FFI.pm @@ -1600,7 +1600,7 @@ $ffi->attach('GDALVectorInfo' => [qw/opaque opaque/] => 'string'); $instance = {}; $instance->{ffi} = $ffi; $instance->{gdal} = $gdal; - #SetErrorHandling(); + SetErrorHandling(); GDALAllRegister(); return bless $instance, $class; } @@ -1822,6 +1822,21 @@ BEGIN { $instance = Geo::GDAL::FFI->new($gdal); } +# +# The next two subs are required for theread-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 diff --git a/t/threads.t b/t/threads.t index d7ea017..03bc43b 100644 --- a/t/threads.t +++ b/t/threads.t @@ -24,8 +24,6 @@ my $nt = 10; for my $i (1..$nt) { my $t = threads->create( sub { - my $gdal = Geo::GDAL::FFI->get_instance; - $gdal->SetErrorHandling; while (my $h = $q->dequeue()) { say "thread out$i: popped $h->{value}"; } @@ -37,8 +35,6 @@ for my $i (1..$nt) { for my $i (1..$nt) { my $t = threads->create( sub { - my $gdal = Geo::GDAL::FFI->get_instance; - $gdal->SetErrorHandling; my $v = rand(100); say "thread in$i: pushed $v"; $q->enqueue({ value => $v }); @@ -47,9 +43,6 @@ for my $i (1..$nt) { push @in_thrds, $t; } -my $gdal = Geo::GDAL::FFI->get_instance; -$gdal->SetErrorHandling; - # try different timing too... :-/ sleep(3); @@ -67,5 +60,4 @@ ok(1, "threading seems ok"); } - done_testing(); From b727cd7f233ec7a1d677bc74fb74f64d1796e8fa Mon Sep 17 00:00:00 2001 From: Francesco Paolo Lovergine Date: Thu, 4 Jan 2024 11:04:15 +0100 Subject: [PATCH 08/18] Added a note about thread-safety and use of SetErrorHandling() within the main thread. --- Changes | 1 + lib/Geo/GDAL/FFI.pm | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/Changes b/Changes index 41eda02..9c4fc5b 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,7 @@ Revision history for Perl extension Geo::GDAL::FFI 0.12 unreleased + - Package is now thread-safe. 0.11 December 19, 2023 - Removed use of to FFI::Platypus::Declare, now discouraged. diff --git a/lib/Geo/GDAL/FFI.pm b/lib/Geo/GDAL/FFI.pm index 87698d9..d60d5dd 100644 --- a/lib/Geo/GDAL/FFI.pm +++ b/lib/Geo/GDAL/FFI.pm @@ -2062,6 +2062,16 @@ confessed if a method fails. This is the default. 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 mostly thread-safe, but for the error handling management. +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 renable 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 From 87a5d6c512c91bf1f822be0b6204b32488103141 Mon Sep 17 00:00:00 2001 From: Francesco Paolo Lovergine Date: Thu, 4 Jan 2024 11:07:21 +0100 Subject: [PATCH 09/18] Removed note in Changes to avoid conflicts with ajolma/master. --- Changes | 1 - 1 file changed, 1 deletion(-) diff --git a/Changes b/Changes index 9c4fc5b..41eda02 100644 --- a/Changes +++ b/Changes @@ -1,7 +1,6 @@ Revision history for Perl extension Geo::GDAL::FFI 0.12 unreleased - - Package is now thread-safe. 0.11 December 19, 2023 - Removed use of to FFI::Platypus::Declare, now discouraged. From 76ac0e339850b8666d380e9002d16bb83c25cf33 Mon Sep 17 00:00:00 2001 From: Francesco Paolo Lovergine Date: Tue, 11 Jun 2024 08:50:37 +0200 Subject: [PATCH 10/18] Updated for typos in comment and POD documentation. --- lib/Geo/GDAL/FFI.pm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Geo/GDAL/FFI.pm b/lib/Geo/GDAL/FFI.pm index d60d5dd..16f198f 100644 --- a/lib/Geo/GDAL/FFI.pm +++ b/lib/Geo/GDAL/FFI.pm @@ -1823,7 +1823,7 @@ BEGIN { } # -# The next two subs are required for theread-safety, because GDAL error handling must be set per thread. +# 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. # @@ -2064,12 +2064,12 @@ handler is set, GDAL prints the errors into stderr. =head1 NOTES ABOUT THREAD-SAFETY -This module is mostly thread-safe, but for the error handling management. +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 renable 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 +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 From a685e774facbe2e1c2c37a50b5ad96612f65333e Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 19 Dec 2023 11:34:37 +1100 Subject: [PATCH 11/18] use strict and warnings in Makefile.PL Update the file accordingly --- Makefile.PL | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index 7297ea1..e093727 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,3 +1,7 @@ +use strict; +use warnings; + +my $have_alien; BEGIN { my $gdal = 'Alien::gdal'; my @argv = (); @@ -27,10 +31,12 @@ BEGIN { my $lib = $a[0]; my $data = "$gdal/share/gdal"; print "I'm creating Geo::GDAL::gdal as a wrapper to $lib, which I believe is GDAL $version.\n"; - $fh = new IO::File; + my $fh = IO::File->new; $fh->open("lib/Geo/GDAL/gdal.pm","w"); print $fh <new; $fh->open("lib/Geo/GDAL/gdal.pm","w"); + print $fh < ['Ari Jolma '], NAME => 'Geo::GDAL::FFI', ABSTRACT_FROM => "lib/Geo/GDAL/FFI.pm", VERSION_FROM => "lib/Geo/GDAL/FFI.pm", LICENSE => "artistic_2", CONFIGURE_REQUIRES => { - Alien::gdal => 0, + 'Alien::gdal' => 0, }, PREREQ_PM => { - PkgConfig => 0.23026, - FFI::Platypus => 0, - PDL => 0, - Sort::Versions => 0, - Alien::gdal => 0, + 'PkgConfig' => 0.23026, + 'FFI::Platypus' => 0, + 'PDL' => 0, + 'Sort::Versions' => 0, + 'Alien::gdal' => 0, }, TEST_REQUIRES => { 'Test::More' => 0, @@ -91,7 +103,7 @@ use Config; }, ); if ($have_alien) { - %agrs = (%args, Alien::Base::Wrapper->mm_args); + %args = (%args, Alien::Base::Wrapper->mm_args); } WriteMakefile(%args); From c1841c304461a6d69c3a72aed592a1a3e45515a2 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 19 Dec 2023 11:34:57 +1100 Subject: [PATCH 12/18] use strict and warnings in dataset_rasterize.t Update the file accordingly --- t/dataset_rasterize.t | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/t/dataset_rasterize.t b/t/dataset_rasterize.t index 9a9ac3f..82d207a 100644 --- a/t/dataset_rasterize.t +++ b/t/dataset_rasterize.t @@ -1,4 +1,7 @@ use 5.010; +use strict; +use warnings; + use Geo::GDAL::FFI; use Test::More; @@ -162,7 +165,7 @@ sub test_Rasterize { sub get_test_raster { - my $name = 'test_ras' . time() + rand() . '.tiff'; + my $name = 'test_ras' . (time() + rand()) . '.tiff'; my $tiff = Geo::GDAL::FFI::GetDriver('GTiff')->Create('test.tiff', 3, 2); my $ogc_wkt = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS84",6378137,298.257223563,'. From 3c0a10a5b67c8a6281278070c14f20def0bab9a3 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 19 Dec 2023 11:14:19 +1100 Subject: [PATCH 13/18] Tests: use Test::TempDir::Tiny and Path::Tiny This avoids potential filename clashes with tests that create and use files on the system. Most tests are unchanged as they use in-memory or vsi files. --- Makefile.PL | 10 ++++++---- t/00.t | 9 ++++++--- t/dataset.t | 6 +++++- t/dataset_rasterize.t | 8 ++++++-- t/open.t | 13 ++++++++----- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/Makefile.PL b/Makefile.PL index e093727..7c98b82 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -83,10 +83,12 @@ my %args = ( 'Alien::gdal' => 0, }, TEST_REQUIRES => { - 'Test::More' => 0, - 'Test::Exception' => 0, - 'JSON' => 0, - 'Data::Dumper' => 0 + 'Test::More' => 0, + 'Test::Exception' => 0, + 'JSON' => 0, + 'Data::Dumper' => 0, + 'Path::Tiny' => 0, + 'Test::TempDir::Tiny' => 0, }, META_MERGE => { "meta-spec" => { version => 2 }, diff --git a/t/00.t b/t/00.t index 56e3612..4320c7d 100644 --- a/t/00.t +++ b/t/00.t @@ -7,6 +7,8 @@ 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/); } @@ -286,8 +288,10 @@ if(1){ # test creating a shapefile if(1){ + my $dir = tempdir(); + my $testfile = path($dir, 'test.shp'); my $dr = GetDriver('ESRI Shapefile'); - my $ds = $dr->Create('test.shp'); + 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)); @@ -297,11 +301,10 @@ if(1){ my $f = Geo::GDAL::FFI::Feature->new($d); $l->CreateFeature($f); undef $l; # otherwise $ds is not flushed due to parent ref - $ds = Open('test.shp'); + $ds = Open($testfile); $l = $ds->GetLayer; $d = $l->GetDefn(); ok($d->GetGeomType eq 'Point', "Create point shapefile and open it."); - unlink qw/test.dbf test.prj test.shp test.shx/; } # test field definitions diff --git a/t/dataset.t b/t/dataset.t index c557843..9acd9bd 100644 --- a/t/dataset.t +++ b/t/dataset.t @@ -6,8 +6,12 @@ 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 $ds = GetDriver('GPKG')->Create('test.gpkg'); +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); foreach my $i (1..3) { my $l = $ds->CreateLayer({ diff --git a/t/dataset_rasterize.t b/t/dataset_rasterize.t index 82d207a..8634feb 100644 --- a/t/dataset_rasterize.t +++ b/t/dataset_rasterize.t @@ -5,6 +5,8 @@ use warnings; use Geo::GDAL::FFI; use Test::More; +use Test::TempDir::Tiny; +use Path::Tiny qw/path/; local $| = 1; @@ -165,8 +167,10 @@ sub test_Rasterize { sub get_test_raster { - my $name = 'test_ras' . (time() + rand()) . '.tiff'; - my $tiff = Geo::GDAL::FFI::GetDriver('GTiff')->Create('test.tiff', 3, 2); + 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,'. diff --git a/t/open.t b/t/open.t index 023de34..76f75a4 100644 --- a/t/open.t +++ b/t/open.t @@ -8,9 +8,14 @@ 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('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(); @@ -21,7 +26,7 @@ use FFI::Platypus::Buffer; my $ds; eval { - $ds = Open('test.shp', { + $ds = Open($testfile, { Flags => [qw/READONLY VERBOSE_ERROR/], AllowedDrivers => [('GML')] }); @@ -31,13 +36,11 @@ $e[0] =~ s/ at .*//; ok($@, "Right driver not in AllowedDrivers: ".$e[0]); eval { - $ds = Open('test.shp', { + $ds = Open($testfile, { Flags => [qw/READONLY VERBOSE_ERROR/], AllowedDrivers => [('GML', 'ESRI Shapefile')] }); }; ok(!@$, "Require right driver in AllowedDrivers"); -unlink qw/test.dbf test.prj test.shp test.shx/; - done_testing(); From f95d774266e372530238f371eaa74131a1cc2a4f Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 19 Dec 2023 11:39:19 +1100 Subject: [PATCH 14/18] CI: install more CPAN deps --- .github/workflows/linux_bin_build.yml | 2 ++ .github/workflows/linux_share_build.yml | 2 ++ .github/workflows/linux_sys_build.yml | 2 ++ .github/workflows/macos.yml | 2 ++ .github/workflows/macos_share_builds.yml | 2 ++ 5 files changed, 10 insertions(+) diff --git a/.github/workflows/linux_bin_build.yml b/.github/workflows/linux_bin_build.yml index 40adb3d..579e556 100644 --- a/.github/workflows/linux_bin_build.yml +++ b/.github/workflows/linux_bin_build.yml @@ -48,6 +48,8 @@ jobs: cpanm --notest Test::Exception cpanm --notest JSON cpanm --notest PDL + cpanm --notest Path::Tiny + cpanm --notest Test::TempDir::Tiny - name: Build run: | diff --git a/.github/workflows/linux_share_build.yml b/.github/workflows/linux_share_build.yml index 1af35e5..51c32c0 100644 --- a/.github/workflows/linux_share_build.yml +++ b/.github/workflows/linux_share_build.yml @@ -49,6 +49,8 @@ jobs: cpanm --notest local::lib echo $(perl -Mlocal::lib=${HOME}/perl5) eval "$(perl -Mlocal::lib=${HOME}/perl5)" + cpanm --notest Path::Tiny + cpanm --notest Test::TempDir::Tiny cpanm --notest PDL cpanm --notest Alien::Build cpanm --installdeps --notest Alien::sqlite diff --git a/.github/workflows/linux_sys_build.yml b/.github/workflows/linux_sys_build.yml index e5b6f11..280fa53 100644 --- a/.github/workflows/linux_sys_build.yml +++ b/.github/workflows/linux_sys_build.yml @@ -57,6 +57,8 @@ jobs: cpanm --notest local::lib echo $(perl -Mlocal::lib=${HOME}/perl5) eval "$(perl -Mlocal::lib=${HOME}/perl5)" + cpanm --notest Path::Tiny + cpanm --notest Test::TempDir::Tiny cpanm --notest PDL cpanm --notest Alien::Build cpanm --installdeps --notest Alien::sqlite diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index ab2d845..a0f67bc 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -56,6 +56,8 @@ jobs: - name: Install Dynamic Dependencies run: | + cpanm --notest Path::Tiny + cpanm --notest Test::TempDir::Tiny cpanm --notest PDL cpanm --notest Alien::Build cpanm --notest Alien::Build::MM diff --git a/.github/workflows/macos_share_builds.yml b/.github/workflows/macos_share_builds.yml index 2ea1c61..a99bf34 100644 --- a/.github/workflows/macos_share_builds.yml +++ b/.github/workflows/macos_share_builds.yml @@ -45,6 +45,8 @@ jobs: - name: Install Dynamic Dependencies run: | + cpanm --notest Path::Tiny + cpanm --notest Test::TempDir::Tiny cpanm --notest PDL cpanm --notest Alien::Build cpanm --notest Alien::Build::MM From 99c76f22ea54b8065900944a04b98ac97e65487f Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 11 Jun 2024 15:41:14 +1000 Subject: [PATCH 15/18] CI: update actions versions --- .github/workflows/linux_bin_build.yml | 2 +- .github/workflows/linux_share_build.yml | 2 +- .github/workflows/linux_sys_build.yml | 4 ++-- .github/workflows/macos.yml | 4 ++-- .github/workflows/macos_share_builds.yml | 2 +- .github/workflows/windows.yml | 6 +++--- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/linux_bin_build.yml b/.github/workflows/linux_bin_build.yml index 579e556..0d6636e 100644 --- a/.github/workflows/linux_bin_build.yml +++ b/.github/workflows/linux_bin_build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shogo82148/actions-setup-perl@v1 with: diff --git a/.github/workflows/linux_share_build.yml b/.github/workflows/linux_share_build.yml index 51c32c0..de350bf 100644 --- a/.github/workflows/linux_share_build.yml +++ b/.github/workflows/linux_share_build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shogo82148/actions-setup-perl@v1 with: diff --git a/.github/workflows/linux_sys_build.yml b/.github/workflows/linux_sys_build.yml index 280fa53..c5a93c4 100644 --- a/.github/workflows/linux_sys_build.yml +++ b/.github/workflows/linux_sys_build.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: shogo82148/actions-setup-perl@v1 with: @@ -43,7 +43,7 @@ jobs: ls -l perlversion.txt - name: Cache CPAN modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/perl5 key: ${{ runner.os }}-build-${{ hashFiles('perlversion.txt') }} diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index a0f67bc..f319ea3 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -20,7 +20,7 @@ jobs: runs-on: macOS-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Perl run: | @@ -47,7 +47,7 @@ jobs: ls -l perlversion.txt - name: Cache CPAN modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ~/perl5 key: ${{ runner.os }}-build-${{ hashFiles('perlversion.txt') }} diff --git a/.github/workflows/macos_share_builds.yml b/.github/workflows/macos_share_builds.yml index a99bf34..6393e34 100644 --- a/.github/workflows/macos_share_builds.yml +++ b/.github/workflows/macos_share_builds.yml @@ -20,7 +20,7 @@ jobs: runs-on: macOS-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Perl run: | diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 02e2888..8eda8b6 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -21,7 +21,7 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Perl run: | @@ -38,7 +38,7 @@ jobs: dir perlversion.txt - name: Cache CPAN modules - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: c:\cx key: ${{ runner.os }}-build-${{ hashFiles('perlversion.txt') }} @@ -46,7 +46,7 @@ jobs: ${{ runner.os }}-build-${{ hashFiles('perlversion.txt') }} - name: Cache Alien downloads - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: C:\Users\runneradmin\.alienbuild key: ${{ runner.os }}-build-${{ hashFiles('aliencache.txt') }} From 1bfc0967936a80abdfaf038b3326a07c4342f6c8 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 11 Jun 2024 15:42:24 +1000 Subject: [PATCH 16/18] CI: Update perl version to 5.38 --- .github/workflows/linux_bin_build.yml | 2 +- .github/workflows/linux_share_build.yml | 2 +- .github/workflows/linux_sys_build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/linux_bin_build.yml b/.github/workflows/linux_bin_build.yml index 0d6636e..f089a79 100644 --- a/.github/workflows/linux_bin_build.yml +++ b/.github/workflows/linux_bin_build.yml @@ -21,7 +21,7 @@ jobs: - uses: shogo82148/actions-setup-perl@v1 with: - perl-version: '5.32' + perl-version: '5.38' - name: Locale check run: | diff --git a/.github/workflows/linux_share_build.yml b/.github/workflows/linux_share_build.yml index de350bf..6bb9d8e 100644 --- a/.github/workflows/linux_share_build.yml +++ b/.github/workflows/linux_share_build.yml @@ -21,7 +21,7 @@ jobs: - uses: shogo82148/actions-setup-perl@v1 with: - perl-version: '5.32' + perl-version: '5.38' - name: cmake for geos run: | diff --git a/.github/workflows/linux_sys_build.yml b/.github/workflows/linux_sys_build.yml index c5a93c4..aa1c6a4 100644 --- a/.github/workflows/linux_sys_build.yml +++ b/.github/workflows/linux_sys_build.yml @@ -21,7 +21,7 @@ jobs: - uses: shogo82148/actions-setup-perl@v1 with: - perl-version: '5.32' + perl-version: '5.38' - name: system libs run: | From f344fcf2316daaca4baba435e2878a22d633a884 Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Tue, 11 Jun 2024 15:43:19 +1000 Subject: [PATCH 17/18] CI: install deps on linux bin build --- .github/workflows/linux_bin_build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/linux_bin_build.yml b/.github/workflows/linux_bin_build.yml index f089a79..d362169 100644 --- a/.github/workflows/linux_bin_build.yml +++ b/.github/workflows/linux_bin_build.yml @@ -54,4 +54,5 @@ jobs: - name: Build run: | perl Makefile.PL + cpanm --notest --installdeps . make test From 19026411130bdb00a71ae195842bc5f19511966e Mon Sep 17 00:00:00 2001 From: shawnlaffan Date: Sun, 29 Oct 2023 20:10:12 +1100 Subject: [PATCH 18/18] Avoid some used-once warnings Fixes #52 --- lib/Geo/GDAL/FFI.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/Geo/GDAL/FFI.pm b/lib/Geo/GDAL/FFI.pm index 16f198f..b156321 100644 --- a/lib/Geo/GDAL/FFI.pm +++ b/lib/Geo/GDAL/FFI.pm @@ -1822,6 +1822,12 @@ BEGIN { $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.