Location>code7788 >text

The resource control problem of GDAL vector dataset related interface

Popularity:575 ℃/2025-02-04 21:59:35

1. Introduction

Author"Read and write vector files with GDAL"This article summarizes the specific implementation of reading and writing vectors through GDAL. However, this article does not talk about resource control issues involving vector datasets related interfaces. Specifically, even the C ++ language itself is not very complete in the birth of GDAL/OGR (before C ++ 11), so the C ++ interface provided often has the problem of releasing resources to be released, so it will be summarized here.

2. Details

2.1 Data Satellite GDALDASET

Vector data set GDALDASET objects need to be read or updated through GDALOPENEX. After this object is not needed, use GDALCLOSE to turn off. For example:

GDALDataset *poDS = (GDALDataset*)GDALOpenEx(filePath, GDAL_OF_VECTOR, NULL, NULL, NULL);

//...

GDALClose(poDS);
poDS = nullptr;

on the other hand,DriveGDALDriverCreate a vector data set,Still use after not neededGDALCloseTurn off。 For example:

GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("ESRI Shapefile");
if (!driver)
{
    printf("Get Driver ESRI Shapefile Error!\n");
    return false;
}
	
GDALDataset* dataset = driver->Create(filePath, 0, 0, 0, GDT_Unknown, NULL);

GDALClose(dataset);
dataset = nullptr;

In theory, after opening or creation, the GDALDASET object is useddeleteIt is also possible to release it. But in general, it is best to use the release interface provided by GDAL itself. Because the internal implementation of this interface may not be as simple as Delete, there may be other resources to release operations. Not just GDAL, other libraries are also the same.

2.2 layer class grlayer

GDALDATASET can be a vector data set or a grid data set. But only vector data sets can obtain or create layer Ogrlayer. However, whether it is acquired or creating OGRLAYER, there is no need to take the initiative to release it after use. The OGRLAYER object will be hosted by the GDALDATASET object. After the GDALCLOSE releases the data set object, the layer Ogrlayer will be released.

Ogrlayer* polayer = pods-> getlayer (0);
 // No need to be explicitly released after obtaining

 Ogrlayer* polayer = dataset-> Createlay ("HouseType", NULL, WKBPOLYGON, NULL);
 // No need to be explicitly released after creation

2.3 Principles OGRFEATUR

The element class OGRFEATURE generally obtains or creates from the layer OGRLAYER object, but it needs to be explicitly released whether it is acquisition or creation. For example, when reading a vector dataset, you traverse the obtaining element:

OGRFeature *poFeature;
while ((poFeature = poLayer->GetNextFeature()) != NULL)
{
    OGRGeometry *pGeo = poFeature->GetGeometryRef();
    //...
    OGRFeature::DestroyFeature(poFeature);
}

HereOGRFeature::DestroyFeature(poFeature);It is a method for destruction of factor objects provided by GDAL. On the other hand, if it is written by the data set creation element, for example, the author creates a vector of the latitude and longitude grid here:

for (int yi = -90; yi < 90; ++yi) {
    for (int xi = -180; xi < 180; ++xi) {    
      OGRFeature poFeature(poLayer->GetLayerDefn());

      OGRLinearRing ogrRing;
      (xi, yi);
      (xi + 1, yi);
      (xi + 1, yi + 1);
      (xi, yi + 1);
      ();

      OGRPolygon polygon;
      (&ogrRing);
      (&polygon);

      if (poLayer->CreateFeature(&poFeature) != OGRERR_NONE) {
        printf("Failed to create feature in shapefile.\n");
        return false;
      }
    }
  }

OGRFEATURE uses the value object, which will be automatically destroyed after exceeding the scope. After verifying the author's writing, there is no problem. It can be inferred that the management of Ogrlayer for the OGRFEARURE object should be a deep copy method, and it will host this copy of the OGRFEARE object.

2.4 Geometry OGRGEOMETRY

Geometry OGRGEOMETRY uses the inheritance and polymorphic characteristics of the C ++ class, which itself is a base class, but inherits subclasses such as OGRLLINEARING, OGRPOLYGON, and other subclasses to express multiple elements and geometry types. Therefore, GDAL provides a factory class to create and destroy, which is a very classic design model:

OGRGEOMETRY* Pogeom = OGRGEOMETRYFACTORY :: Creategeometry (wkbpoint);
 // Release it after using pogeom
 Ogrgeometryfactory :: Destroygeometry (Pogeom);

That is, OGRGEOMETRYFACTORY :: Creategeometry and OGRGEOMETRYFACTORY :: Destroygeometry need to be paired. However, the author believes that if it is not for polymorphism, it is more convenient to use the value of the value directly, as shown in the example 2.3.

In addition, the OGRGEOMETRY object needs to be placed in the OGRFEATURE object, so OGRFEATURE provides two interfaces:

  1. OGRErr SetGeometryDirectly(OGRGeometry*): Ogrgeometry object, the OGRFEATURE object directly hosted the ownership of the OGRGEOMETRY object.
  2. OGRErr SetGeometry(const OGRGeometry*): Deep copy of the OGRGEOMETRY object, the OGRFEATURE object custody OGRGEOMETRY copy the ownership of the object.

In addition, the mutual reference between geometry is also the same. As shown in the examples in Section 2.3, there are two interfaces in the polygon increase ring:

  1. addRingDirectly()A shallow copy of the Ogrlinearring object, the OGRPOLYGON object directly hosts the ownership of the Ogrlinearring object.
  2. addRing()Deep copy of the Ogrlinearring object, the OGRPOLYGON object custody OGRLLINEARING copy the ownership of the object.

In general, GDAL usually uses the function interface of the Directly suffix to express the hosting of the original geometric object.

3. Other

It can be seen that GDAL's resource control is still a bit confusing. Some of them are explicitly released, some can host, and some simply provide two interfaces. It is said that the new GDAL version has introduced a lot of new C ++ features, and the logic of estimated resource control should be clearer. In addition, we can also actively use some new C ++ features to avoid the problem of active release of resource control. For example, using a smart pointer, with a custom deleter to destroy the OGRFEATURE object, as shown in the following example:

// Get the first layer
 Ogrlayer* polayer = pods-> getlayer (0);
 if (POLAYER == NULLPTR) {
     STD :: CERR << "FAILED to get the layer." << STD :: Endl;
     GdalClose (pods);
     Return -1;
 }

 // Custom deletioner is used to destroy OGRFEATUR
 Auto Featuredeleter = [] (OGRFEATURE* POFEATURE) {
     OGRFEATURE :: Destroyfeature (Pofeature);
 };

 // Elementary elements in the layer
 polayer-> resetreaming ();
 std :: unique_ptr <ogrfeature, DEATUREDELETER)> POFEATURE (NULLPTR, Featuredeleter);

 While ((Polay-> GetNextfeature ()), POFEATURE) {
     // Get geometry
     OGRGEOMETRY* POGEOMETRY = POFEATURE-> Getgeometryref ();
     if (pogeometry! = NullPtr) {
         // Output geometry wkt representation
         char* pszwkt = nullptr;
         pogeometry-> Exporttowkt (& PSZWKT);
         STD :: COUT << "Geometry:" << pszwkt << std :: endl;
         CPLFREE (PSZWKT); // Release the WKT string
     }
 }