diff --git a/filters/OverlayFilter.cpp b/filters/OverlayFilter.cpp
index 5246779..590ddcc 100644
--- a/filters/OverlayFilter.cpp
+++ b/filters/OverlayFilter.cpp
@@ -93,7 +93,7 @@ void OverlayFilter::prepared(PointTableRef table)
 void OverlayFilter::ready(PointTableRef table)
 {
     m_ds = OGRDSPtr(OGROpen(m_datasource.c_str(), 0, 0),
-            [](void *p){ if (p) ::OGR_DS_Destroy(p); });
+            [](OGRDSPtr::element_type *p){ if (p) ::OGR_DS_Destroy(p); });
     if (!m_ds)
         throwError("Unable to open data source '" + m_datasource + "'");
 
@@ -114,7 +114,7 @@ void OverlayFilter::ready(PointTableRef table)
         OGR_L_SetSpatialFilter(m_lyr, g.getOGRHandle());
     }
 
-    auto featureDeleter = [](void *p)
+    auto featureDeleter = [](OGRFeaturePtr::element_type *p)
     {
         if (p)
             ::OGR_F_Destroy(p);
diff --git a/filters/OverlayFilter.hpp b/filters/OverlayFilter.hpp
index c9995d7..141bf51 100644
--- a/filters/OverlayFilter.hpp
+++ b/filters/OverlayFilter.hpp
@@ -41,6 +41,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <type_traits>
 
 // Get GDAL's forward decls if available
 // otherwise make our own
@@ -58,9 +59,13 @@ namespace gdal
     class ErrorHandler;
 }
 
+#if __has_include(<gdal_fwd.h>)
+typedef std::shared_ptr<std::remove_pointer<OGRDataSourceH>::type> OGRDSPtr;
+typedef std::shared_ptr<std::remove_pointer<OGRFeatureH>::type> OGRFeaturePtr;
+#else
 typedef std::shared_ptr<void> OGRDSPtr;
 typedef std::shared_ptr<void> OGRFeaturePtr;
-typedef std::shared_ptr<void> OGRGeometryPtr;
+#endif
 
 class Arg;
 
@@ -90,8 +95,6 @@ private:
     OverlayFilter& operator=(const OverlayFilter&) = delete;
     OverlayFilter(const OverlayFilter&) = delete;
 
-    typedef std::shared_ptr<void> OGRDSPtr;
-
     OGRDSPtr m_ds;
     OGRLayerH m_lyr;
     std::string m_dimName;
diff --git a/io/TIndexReader.cpp b/io/TIndexReader.cpp
index 0d9c4ca..551b3ea 100644
--- a/io/TIndexReader.cpp
+++ b/io/TIndexReader.cpp
@@ -89,7 +89,7 @@ TIndexReader::FieldIndexes TIndexReader::getFields()
 {
     FieldIndexes indexes;
 
-    void *fDefn = OGR_L_GetLayerDefn(m_layer);
+    OGRFeatureDefnH fDefn = OGR_L_GetLayerDefn(m_layer);
 
     indexes.m_filename = OGR_FD_GetFieldIndex(fDefn,
         m_args->m_tileIndexColumnName.c_str());
diff --git a/io/TIndexReader.hpp b/io/TIndexReader.hpp
index 1188a1c..ccedfb6 100644
--- a/io/TIndexReader.hpp
+++ b/io/TIndexReader.hpp
@@ -41,6 +41,15 @@
 
 #include <pdal/JsonFwd.hpp>
 
+// Get GDAL's forward decls if available
+// otherwise make our own
+#if __has_include(<gdal_fwd.h>)
+#include <gdal_fwd.h>
+#else
+using OGRDataSourceH = void *;
+using OGRLayerH = void *;
+#endif
+
 namespace pdal
 {
 
@@ -88,8 +97,8 @@ private:
 
     std::unique_ptr<Args> m_args;
     std::unique_ptr<gdal::SpatialRef> m_out_ref;
-    void *m_dataset;
-    void *m_layer;
+    OGRDataSourceH m_dataset;
+    OGRLayerH m_layer;
 
     StageFactory m_factory;
     MergeFilter m_merge;
diff --git a/kernels/TIndexKernel.cpp b/kernels/TIndexKernel.cpp
index 1f43c75..82d6c81 100644
--- a/kernels/TIndexKernel.cpp
+++ b/kernels/TIndexKernel.cpp
@@ -723,7 +723,7 @@ TIndexKernel::FieldIndexes TIndexKernel::getFields()
 {
     FieldIndexes indexes;
 
-    void *fDefn = OGR_L_GetLayerDefn(m_layer);
+    OGRFeatureDefnH fDefn = OGR_L_GetLayerDefn(m_layer);
 
     indexes.m_filename = OGR_FD_GetFieldIndex(fDefn,
         m_tileIndexColumnName.c_str());
diff --git a/kernels/TIndexKernel.hpp b/kernels/TIndexKernel.hpp
index a6d8930..72849f7 100644
--- a/kernels/TIndexKernel.hpp
+++ b/kernels/TIndexKernel.hpp
@@ -40,6 +40,15 @@
 #include <pdal/SubcommandKernel.hpp>
 #include <pdal/util/FileUtils.hpp>
 
+// Get GDAL's forward decls if available
+// otherwise make our own
+#if __has_include(<gdal_fwd.h>)
+#include <gdal_fwd.h>
+#else
+using OGRDataSourceH = void *;
+using OGRLayerH = void *;
+#endif
+
 namespace pdal
 {
     class Polygon;
@@ -118,8 +127,8 @@ private:
     BOX2D m_bounds;
     bool m_absPath;
 
-    void *m_dataset;
-    void *m_layer;
+    OGRDataSourceH m_dataset;
+    OGRLayerH m_layer;
     std::string m_tgtSrsString;
     std::string m_assignSrsString;
     bool m_fastBoundary;
diff --git a/kernels/private/density/OGR.hpp b/kernels/private/density/OGR.hpp
index 243a67a..f61ad4e 100644
--- a/kernels/private/density/OGR.hpp
+++ b/kernels/private/density/OGR.hpp
@@ -35,6 +35,15 @@
 
 #include <string>
 
+// Get GDAL's forward decls if available
+// otherwise make our own
+#if __has_include(<gdal_fwd.h>)
+#include <gdal_fwd.h>
+#else
+using OGRDataSourceH = void *;
+using OGRLayerH = void *;
+#endif
+
 namespace hexer
 {
     class HexGrid;
@@ -45,9 +54,6 @@ namespace pdal
 
 class OGR
 {
-    using OGRDataSourceH = void *;
-    using OGRLayerH = void *;
-
 public:
     OGR(std::string const& filename, const std::string& srs,
         std::string driver = "ESRI Shapefile", std::string layerName ="");
diff --git a/pdal/Geometry.cpp b/pdal/Geometry.cpp
index c598e66..fec6107 100644
--- a/pdal/Geometry.cpp
+++ b/pdal/Geometry.cpp
@@ -275,11 +275,11 @@ Geometry Geometry::getRing() const
 {
     throwNoGeos();
 
-    int count = OGR_G_GetGeometryCount(m_geom.get());
+    int count = OGR_G_GetGeometryCount(gdal::toHandle(m_geom.get()));
     if (count)
     {
 
-        OGRGeometryH ring = OGR_G_Clone(OGR_G_GetGeometryRef(m_geom.get(), 0));
+        OGRGeometryH ring = OGR_G_Clone(OGR_G_GetGeometryRef(gdal::toHandle(m_geom.get()), 0));
         OGRGeometryH linestring = OGR_G_ForceToLineString(ring);
 
         return Geometry(linestring, getSpatialReference());
diff --git a/pdal/SpatialReference.cpp b/pdal/SpatialReference.cpp
index cf7abaa..7aec1b6 100644
--- a/pdal/SpatialReference.cpp
+++ b/pdal/SpatialReference.cpp
@@ -53,22 +53,13 @@
 namespace
 {
 
-struct OGRDeleter
-{
-    void operator()(OGRSpatialReference* o)
-    {
-        OSRDestroySpatialReference(o);
-    };
-};
-
 using OGRScopedSpatialReference =
-    std::unique_ptr<OGRSpatialReference, OGRDeleter>;
+    std::unique_ptr<OGRSpatialReference>;
 
 OGRScopedSpatialReference ogrCreateSrs(std::string s = "", double epoch=0.0)
 {
     OGRScopedSpatialReference r(
-        static_cast<OGRSpatialReference*>(
-            OSRNewSpatialReference(s.size() ? s.c_str() : nullptr)));
+        new OGRSpatialReference(s.size() ? s.c_str() : nullptr));
     if (!pdal::Utils::compare_approx(epoch, 0.0f, 0.00001f))
     {
 #if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,4,0)
@@ -129,7 +120,7 @@ bool SpatialReference::valid() const
 {
     OGRSpatialReference current(m_wkt.data());
 
-    return OSRValidate(&current) == OGRERR_NONE;
+    return current.Validate() == OGRERR_NONE;
 }
 
 
@@ -367,7 +358,7 @@ bool SpatialReference::equals(const SpatialReference& input) const
     if (!current || !other)
         return false;
 
-    int output = OSRIsSame(current.get(), other.get());
+    int output = current.get()->IsSame(other.get());
 
     return (output == 1);
 }
@@ -398,7 +389,7 @@ bool SpatialReference::isGeographic() const
     if (!current)
         return false;
 
-    bool output = OSRIsGeographic(current.get());
+    bool output = current.get()->IsGeographic();
     return output;
 }
 
@@ -409,7 +400,7 @@ bool SpatialReference::isGeocentric() const
     if (!current)
         return false;
 
-    bool output = OSRIsGeocentric(current.get());
+    bool output = current.get()->IsGeocentric();
     return output;
 }
 
@@ -420,7 +411,7 @@ bool SpatialReference::isProjected() const
     if (!current)
         return false;
 
-    bool output = OSRIsProjected(current.get());
+    bool output = current.get()->IsProjected();
     return output;
 }
 
@@ -573,7 +564,7 @@ int SpatialReference::getUTMZone() const
         throw pdal_error("Could not fetch current SRS");
 
     int north(0);
-    int zone = OSRGetUTMZone(current.get(), &north);
+    int zone = current.get()->GetUTMZone(&north);
     return (north ? 1 : -1) * zone;
 }
 
diff --git a/pdal/private/gdal/GDALUtils.cpp b/pdal/private/gdal/GDALUtils.cpp
index b9d295c..04b7c17 100644
--- a/pdal/private/gdal/GDALUtils.cpp
+++ b/pdal/private/gdal/GDALUtils.cpp
@@ -357,7 +357,7 @@ std::vector<Polygon> getPolygons(const OGRSpecOptions& ogr)
                 throw pdal_error("Unable to execute OGR SQL query.");
 
             SpatialRef sref;
-            sref.setFromLayer(poLayer);
+            sref.setFromLayer(reinterpret_cast<OGRLayerH>(poLayer));
             ds->ReleaseResultSet(poLayer);
 
             poly.update(options.at("geometry").get<std::string>());
@@ -380,7 +380,7 @@ std::vector<Polygon> getPolygons(const OGRSpecOptions& ogr)
     std::vector<Polygon> polys;
     while ((poFeature = poLayer->GetNextFeature()) != NULL)
     {
-        polys.emplace_back(poFeature->GetGeometryRef());
+        polys.emplace_back(reinterpret_cast<OGRGeometryH>(poFeature->GetGeometryRef()));
         OGRFeature::DestroyFeature( poFeature );
     }
 
diff --git a/pdal/private/gdal/SpatialRef.cpp b/pdal/private/gdal/SpatialRef.cpp
index 049867e..63bba9e 100644
--- a/pdal/private/gdal/SpatialRef.cpp
+++ b/pdal/private/gdal/SpatialRef.cpp
@@ -106,9 +106,9 @@ bool SpatialRef::empty() const
     return wkt().empty();
 }
 
-void SpatialRef::newRef(void *v)
+void SpatialRef::newRef(OGRSpatialReferenceH v)
 {
-    m_ref = RefPtr(v, [](void* t){ OSRDestroySpatialReference(t); } );
+    m_ref = RefPtr(v, [](OGRSpatialReferenceH t){ OSRDestroySpatialReference(t); } );
 }
 
 } // namespace gdal
diff --git a/pdal/private/gdal/SpatialRef.hpp b/pdal/private/gdal/SpatialRef.hpp
index 4d2b34d..80a114c 100644
--- a/pdal/private/gdal/SpatialRef.hpp
+++ b/pdal/private/gdal/SpatialRef.hpp
@@ -35,6 +35,7 @@
 #pragma once
 
 #include <memory>
+#include <type_traits>
 
 // Get GDAL's forward decls if available
 // otherwise make our own
@@ -42,6 +43,7 @@
 #include <gdal_fwd.h>
 #else
     using OGRLayerH = void *;
+    using OGRSpatialReferenceH = void *;
 #endif
 
 
@@ -53,7 +55,7 @@ namespace gdal
 
 class SpatialRef
 {
-    typedef std::shared_ptr<void> RefPtr;
+    typedef std::shared_ptr<std::remove_pointer<OGRSpatialReferenceH>::type> RefPtr;
 public:
     SpatialRef();
     SpatialRef(const std::string& srs);
@@ -65,7 +67,7 @@ public:
     bool empty() const;
 
 private:
-    void newRef(void *v);
+    void newRef(OGRSpatialReferenceH v);
 
     RefPtr m_ref;
 };
