Skip to content

Csharp SWIG bindings overhaul - #15079

Open
Mbucari wants to merge 23 commits into
OSGeo:masterfrom
Mbucari:csharp_overhaul
Open

Mbucari wants to merge 23 commits into
OSGeo:masterfrom
Mbucari:csharp_overhaul

Conversation

@Mbucari

@Mbucari Mbucari commented Aug 23, 2026 •

Copy link
Copy Markdown
Contributor

What does this PR do?

Overhauls the C# SWIG bindings by:

  • Adding multi-argument typemaps for arrays/lists
  • Fixing broken typemaps (eg. GDALProgressFuncDelegate 'argout') and adding new ones (eg. CTYPE **array_argout_free)
  • Enabling automatic overload generation (like exists for Java), and C# default arguments (for SWIG_VERSION >= 4.2.0)
  • Added QOL helper methods (e.g. SetFieldAsDateTime and GetFieldAsDateTime using System.DateTime)
  • Cleaned up SWIG interface files by removing obsolete and redundant code, adding more macro-generated tyemaps, and consolidating similar functionality.

New Methods exposed to C#

This PR exposes several new GDAL functions. See the list below, and use checkboxes to track their review.

List of new GDAL methods exposed to C#
  • OSGeo.OSR.CoordinateTransformation.TransformPointsWithErrorCodes
  • OSGeo.OGR.Feature
    • SetFieldInteger64List
    • GetFieldAsInteger64List
    • SetFieldBinary
    • GetFieldAsBinary
    • Overloads for all field getter/setters that accept field names
  • OSGeo.OGR.FldDomain.GetEnumeration
  • OSGeo.OGR.Geometry
    • WkbLongSize (property)
    • ExportToIsoWkb
  • OSGeo.OGR.Layer
    • GetDataset (via an OSGeo.GDAL extension method)
    • GetExtent (overload which accepts int geom_field)
    • GetExtent3D
  • OSGeo.OGR.Ogr
    • CreateCodedFieldDomain
    • CreateGeometryFromEnvelope
  • OSGeo.GDAL.AlgorithmArg
    • GetDefaultAsIntegerList
    • GetDefaultAsDoubleList
    • GetAsIntegerList
    • GetAsDoubleList
    • SetDatasets
  • OSGeo.GDAL.Band
    • GetHistogramEx
    • GetDefaultHistogramEx
    • SetDefaultHistogramEx
  • OSGeo.GDAL.Dataset
    • SetGCPs2 (accepts a SpatialReference object)
    • CreateLayer
    • CreateLayerFromGeomFieldDefn
    • CopyLayer
    • ExecuteSQL
    • ReleaseResultSet
    • GetStyleTable
    • SetStyleTable
  • OSGeo.GDAL.ExtendedDataType.CreateCompound
  • OSGeo.GDAL.Gdal.GetOpenDatasets
  • OSGeo.GDAL.RATDateTime.ctor
  • OSGeo.GDAL.RATDateTime..ctor

New Helper Methods

I added some new helper methods which are implemented purely in .NET

List of new helper C# methods
  • OSGeo.OGR.Geometry
    • byte[] ExportToWkb(wkbByteOrder byte_order)
    • byte[] ExportToIsoWkb(wkbByteOrder byte_order)
    • GetExtent3D(out double x, out double y)
    • GetExtent3D(out double x, out double y, out double z)
    • GetExtent3D(out double x, out double y, out double z, out double m)
  • OSGeo.OGR.Feature
    • GetFieldAsDateTime(int id)
    • GetFieldAsDateTime(string field_name)
  • OSGeo.GDAL.RATDateTime
    • FromDateTimeOffset
    • ToDateTimeOffset
  • OSGeo.GDAL.RasterIOExtraArg
    • SetProgressDelegate
    • SetProgressDelegate<TData>

Method Signature Changes

For existing C# methods whose signature changed due to the new typemaps, I added those methods back and marked them as obsolete with messages directing users to the replacement method. Most of those obsolete methods are forwarded to the new method signature, but some will be marked as an error and will throw a NotSupportedException. See the list below, and use checkboxes to track their review.

List of existing C# methods which this PR marks as obsolete

Methods marked with ❌ are marked as compiler errors and trow a NotSupportedException.

  • OSGeo.OSR.CoordinateTransformation
    • TransformPoints(int, double[], double[], double[])
  • OSGeo.OSR.SpatialReference
    • ExportToPCI(out string, out string) (fixed typemap to enable out double[] params_)
    • ExportToUSGS(out int, out int, out int) (fixed typemap to enable out double[] params_)
    • SetDataAxisToSRSAxisMapping(int, int[])
    • FindMatches(string[], out int, out int[])
  • OSGeo.OGR.Feature
    • SetFieldDoubleList(int, int, double[])
    • SetFieldIntegerList(int, int, int[])
    • SetFromWithMap(Feature, int, int, int[])
  • OSGeo.OGR.Geometry
    • ExportToWkb(int, IntPtr, wkbByteOrder)
    • .ctor(wkbGeometryType, string, int, IntPtr, string)
  • OSGeo.OGR.Layer
    • ReorderFields(int, int[])
    • UpdateFeature(Feature, int, int[], int, int[], bool)
  • OSGeo.OGR.Ogr
    • CreateGeometryFromWkb(uint, IntPtr, SpatialReference)
  • OSGeo.GDAL.AlgorithmArg
    • SetAsIntegerList(int, int[])
    • SetAsDoubleList(int, double[])
  • OSGeo.GDAL.Band
    • MaximumOfNBands(int, Band[])
    • MeanOfNBands(int, Band[])
    • MinimumOfNBands(int, Band[])
    • GetHistogram(double, double, int, int[], int, int, GDALProgressFuncDelegate, string)
    • AdviseRead(int, int, int, int, ref int, ref int, ref int, string[])
    • Checksum(int, int, ref int, ref int)
    • SetDefaultHistogram(double, double, int, int[])
    • GetDefaultHistogram(out double, out double, out int, out int[], int, GDALProgressFuncDelegate, string)
  • OSGeo.GDAL.Dataset
    • AdviseRead(int, int, int, int, ref int, ref int, ref int, int, int[], string[])
    • BuildOverviews(string, int, IntPtr, GDALProgressFuncDelegate, string, string[])
    • GetNextFeature(ref IntPtr, ref double, GDALProgressFuncDelegate, string)
  • OSGeo.GDAL.Group
    • ❌ CreateAttribute(string, int, uint[], ExtendedDataType, string[])
  • OSGeo.GDAL.MDArray
    • ❌ CreateAttribute(string, int, uint[], ExtendedDataType, string[])
    • ❌ Resize(int, uint[], string[])
    • Transpose(int, int[])
  • OSGeo.GDAL.Transformer
    • ❌ TransformPoints(int, int, double[], double[], double[], double[])
  • OSGeo.GDAL.Gdal
    • VSIFWriteL(string, int, int, IntPtr)
    • ❌ GCPsToHomography(int, IntPtr, double[])
    • RasterizeLayer(Dataset, int, int[], Layer, IntPtr, IntPtr, int, double[], string[], GDALProgressFuncDelegate, string)
    • RegenerateOverviews(Band, int, Band[], string, GDALProgressFuncDelegate, string)
    • ContourGenerate(Band, double, double, int, double[], int, double, Layer, int, int, GDALProgressFuncDelegate, string)
    • CreatePansharpenedVRT(string, Band, int, Band[])
    • ❌ wrapper_GDALBuildVRT_objects(string, int, IntPtr, GDALBuildVRTOptions, GDALProgressFuncDelegate, string)
    • ❌ wrapper_GDALMultiDimTranslateDestName(string, int, IntPtr, GDALMultiDimTranslateOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALContourDestDS(Dataset, Dataset, GDALContourOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALContourDestName(string, Dataset, GDALContourOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALDEMProcessing(string, Dataset, string, string, GDALDEMProcessingOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALFootprintDestDS(Dataset, Dataset, GDALFootprintOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALFootprintDestName(string, Dataset, GDALFootprintOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALGrid(string, Dataset, GDALGridOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALNearblackDestDS(Dataset, Dataset, GDALNearblackOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALNearblackDestName(string, Dataset, GDALNearblackOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALRasterizeDestDS(Dataset, Dataset, GDALRasterizeOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALRasterizeDestName(string, Dataset, GDALRasterizeOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALTranslate(string, Dataset, GDALTranslateOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALVectorTranslateDestDS(Dataset, Dataset, GDALVectorTranslateOptions, GDALProgressFuncDelegate, string)
    • wrapper_GDALVectorTranslateDestName(string, Dataset, GDALVectorTranslateOptions, GDALProgressFuncDelegate, string)
    • wrapper_TileIndex_names(string, string[], GDALTileIndexOptions, GDALProgressFuncDelegate, string)
    • All static GDAL_GCP_* property getters/setters

Method Changes Which Should Be Transparent to the Caller

Some methods were changed in ways that shouldn't require any changes by users (e.g. changing a parameter type from int to long or adding a new parameter that has a default argument). These changes have the potential to be breaking if these methods are cast to delegates, but they should not cause problems if called normally. See the list below, and use checkboxes to track their review.

List of transparent changes
  • OSGeo.GDAL.Band.ExportToWkb(byte[] buffer) (new method has second argument with a default value)
  • OSGeo.OGR.Geometry..ctor(wkbGeometryType type) (new method has additional argument with a default value)
  • All OSGeo.GDAL.Band.ReadRaster, OSGeo.GDAL.Band.WriteRaster, OSGeo.GDAL.Dataset.ReadRaster, and OSGeo.GDAL.Band.WriteRaster methods (changed pixelSpace and lineSpace types to long and extraArg has default value null)
  • Dataset.BuildOverviews(string, int[]) and Dataset.BuildOverviews(string, int[], GDALProgressFuncDelegate, string) (new method has additional argument with a default value)

Methods Signatures Changed With No Replacement (breaking)

There is only one method that was changed without adding replacements or obsolete messages: OSGeo.GDAL.MDArray.BuildOverviews(string, int, SWIGTYPE_p_int, GDALProgressFuncDelegate callback, string, string[]). This method was properly type mapped a to accept an int[].

Types Removed

Due to typemap fixes in this PR, OSGeo.GDAL.SWIGTYPE_p_GDALProgressFunc and OSGeo.GDAL.SWIGTYPE_p_int are no longer in the Assembly. This is a breaking change, but I doubt anyone was using them.

What are related issues/pull requests?

#3041
#10534

AI tool usage

  • AI (I read Google's AI overviews and I used Copilot autocomplete suggestions within Visual Studio. This PR description was written without AI.)

Tasklist

  • Make sure code is correctly formatted (pre-commit failed on files not modified by this PR)
  • Add test case(s)
  • Review
  • Adjust for comments
  • All CI builds and checks have passed
  • ADD YOUR TASKS HERE

Environment

Provide environment details, if relevant:

  • OS: Windows 11
  • Compiler: MSVC 14.51.36231; MSBuild version 18.9.1

@Mbucari Mbucari changed the title Csharp overhaul Csharp SWIG bindings overhaul Aug 23, 2026
@Mbucari

Mbucari commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@runette

@runette

runette commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

@Mbucari - this is a big PR and it is going to take time to review and because of the scale of the ABI changes we are probably going to have to discuss when to bring it in. That is not to say tthat an overhaul like this is not overdue!

As a starting point - you have a very nice list of the new methods (thank you). Is it possible to add a list of the obsoleted/changed methods (or method signatures). That will review a lot easier - having a list to tick off.

@Mbucari

Mbucari commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor Author

we are probably going to have to discuss when to bring it in.

@runette - Completely understandable, and I'd like to be a part of those discussions. Is there a formal process needed to kick-off a community review? Should you (a project Collaborator) or I (the PR author) spearhead the committee discussion/review?

(thank you) Is it possible to add a list of the obsoleted/changed methods (or method signatures).

You're very welcome. I've updated the PR comment with 3 new lists. I build a .NET assembly diff tool, so let me know if you want me to make any other queries or comparisons.

@Mbucari

Mbucari commented Aug 25, 2026 •

Copy link
Copy Markdown
Contributor Author

Note that the "cs:defaultargs" feature requires SWIG >= v4.2.0. All workflows which build the C# bindings are using SWIG >= v4.2.0, but GDAL only requires SWIG >= 4.0.0. If SWIG < v4.2.0 then automatic overloads will be created instead (like Java). This could be problematic for multi-platform devs (of whom I am one). I checked @MaxRev-Dev's build systems and found that Windows uses v4.4.1, Mac uses v4.5.0, and Linux uses v4.1.0. The result is that the same package version would have a different ABI surface on Linux than it does on Windows and Mac.

@jratike80

Copy link
Copy Markdown
Collaborator

@szekerest , by the documentation https://gdal.org/en/stable/api/csharp/index.html you have been maintaining these things.

@szekerest

Copy link
Copy Markdown
Contributor

@szekerest , by the documentation https://gdal.org/en/stable/api/csharp/index.html you have been maintaining these things.

Formerly yes, but feel free to update the document as needed.

@jratike80

Copy link
Copy Markdown
Collaborator

Formerly yes, but feel free to update the document as needed.

How about your gisinternals builds, would they, and you, be happy with these SWIG changes?

@runette

runette commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

we are probably going to have to discuss when to bring it in.

@runette - Completely understandable, and I'd like to be a part of those discussions. Is there a formal process needed to kick-off a community review? Should you (a project Collaborator) or I (the PR author) spearhead the committee discussion/review?

(thank you) Is it possible to add a list of the obsoleted/changed methods (or method signatures).

You're very welcome. I've updated the PR comment with 3 new lists. I build a .NET assembly diff tool, so let me know if you want me to make any other queries or comparisons.

@Mbucari Sorry if I worded it badly - I definitely meant "have a conversation in this PR " and you need to be involved and driving it - as you have. Even is usually the keeper of releases - I will start the process below.

@runette

runette commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

@rouault - a heads up that we have this PR that involves changes to the ABI.

I have not started reviewing it but I am aware we will have to be carefull about how we fit this into the relese schedule.

Note for all - I am about to spend the nexf five days working in a field! So, do not be concerned if I seem to go quiet for periods.

@runette

runette commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Note that the "cs:defaultargs" feature requires SWIG >= v4.2.0. All workflows which build the C# bindings are using SWIG >= v4.2.0, but GDAL only requires SWIG >= 4.0.0. If SWIG < v4.2.0 then automatic overloads will be created instead (like Java). This could be problematic for multi-platform devs (of whom I am one). I checked @MaxRev-Dev's build systems and found that Windows uses v4.4.1, Mac uses v4.5.0, and Linux uses v4.1.0. The result is that the same package version would have a different ABI surface on Linux than it does on Windows and Mac.

That is going to be an issue. It is not just the people who distribute binary versions - people might be building themeselves and the publsihed requirements say SWIG>4 and not 4.2.

To change that will require an RFC and has dependencies across the Python, Java and C# interfaces (which I am sure you know).

@MaxRev-Dev - is there a reason why you are using SWIG 4.1 for Linux. That could shape the conversation.

@Mbucari

Mbucari commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

That is going to be an issue. It is not just the people who distribute binary versions - people might be building themeselves and the publsihed requirements say SWIG>4 and not 4.2.

The SWIG interfaces conditionally enable that feature #if SWIG_VERSION >= 0x040200, so it does not change the build requirement.

@runette

runette commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

That is going to be an issue. It is not just the people who distribute binary versions - people might be building themeselves and the publsihed requirements say SWIG>4 and not 4.2.

The SWIG interfaces conditionally enable that feature #if SWIG_VERSION >= 0x040200, so it does not change the build requirement.

Good to know it will not crash, however we should take a deep breath before deliberately introducing ABI differences that depends on the SWIG version. I think that you might be about to say that we have them already - but that is not the same as intentionality. I guess not impossible but not a simple yes.

I will have to pick this up after the weekend

@Mbucari

Mbucari commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Changes from SWIG 4.0.0 -> 4.2.0

SWIG 4.0.0 SWIG 4.2.0
Release Date 27 Apr 2019 30 Dec 2023
Min 3.x python version 3.2 3.3
Max 3.x python version 3.7 3.12
parser (to build SWIG from source) "yacc or bison" "Bison 3.5.0 or higher"

@rouault

rouault commented Aug 27, 2026

Copy link
Copy Markdown
Member

a heads up that we have this PR that involves changes to the ABI.

I assume the methods that are no longer available were broken or barely usable because of missing typemaps ? That seem fine to me. That can be documented in doc/source/user/migration_guide.rst

@Mbucari

Mbucari commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

I assume the methods that are no longer available were broken or barely usable because of missing typemaps ?

Correct.

That can be documented in doc/source/user/migration_guide.rst

Done.

@MaxRev-Dev

Copy link
Copy Markdown
Contributor

is there a reason why you are using SWIG 4.1 for Linux.

Those SWIG binaries are just installed from package managers (here and here). I didn't bother with versioning as it didn't cause any issues using different minor versions. I can pin them respectfully to 4.2.0+.
Thanks for asking and noticing. I'll address this soon.

@Mbucari

Mbucari commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Thank you, @MaxRev-Dev.

@szekerest I see your build systems are all using SWIG 4.0.2. are you willing to upgrade to 4.2.0?

@Mbucari
Mbucari force-pushed the csharp_overhaul branch 2 times, most recently from 34d8be7 to 1c81e93 Compare August 29, 2026 06:05
- Add ArrayHelper class to help marshal arrays of Gdal objects and primitives to/from GDAL
- Expose additional functions for C# which had previously only been exposed for Java/python.
- Add multi-argument typemaps to map C# arrays to/from GDAL functions which accept list size and list pointer arguments, which already exist in Java and python. This causes the method signatures to changes for several methods which accept array arguments.
- Fix `CTYPE *argout[ANY]` typemaps not working correctly, which fixes `SpatialReference` methods `ExportToPCI` and `ExportToUSGS`.
- Fix incorret typemap applied to `panSuccess` argument in `GDAL.Transformer.TransformPoints`.
- Fix GUIntBig arrays incorrectly being typemapped to C# uint arrays, now mapped to long arrays.
- Fix incomplete typemap definitions for `GDALProgressFunc`.
- Improve `GDALRasterIOExtraArg`
  - Expose existing `GDALRasterIOExtraArg` struct in SWIG instead of re-defining it.
  - Add support for progress delegates with string messages and C# object data.
- OGRLayerShadow **ppoBelongingLayer typemap is now `out Layer` instead of `ref IntPtr`
- Expose GDALGetOpenDatasets for C#
Several method signatures were changed due to changes in typemaps. Re-add all methods that were removed and mark them as obsolete. For removed methods whose arguments are easily mapped onto the new methods, create an overload accessing the new method. For all other removed methods, mark the obsolete function as an error.
- consolidated all SWIGTYPE typedefs
- Remove SWIG_VERSION  <= 0x020000 code since SWIG 4.0 or greater is required.
 - SWIGTYPEs throw exception if accessed after disposed instead of causing a crash
- Add multi-argument byte array support for (int nList, char* pList)
- Add backwards compatibility overload for old Geometry constructor
Disable the swig feature "compactdefaultargs" for C# so that SWIG generates overloads for all methods which have default arguments.
- Use the Java renamings for "wrapper_*" method names.
- Add overloads for "wrapper_*" methods which point to the new methods names and are tagged obsolete.
- Add overloads to get/set values by field name
- Add C# support for int64 list
Mbucari and others added 13 commits August 29, 2026 00:06
- Use GDALRATDateTime typedef from gdal.h and extend it with constructors and destructor
- Add C# Feature overloads to get/set date fields as System.DateTime
- Add C# functions to convert RATDateTime to/from DateTimeOffset
- Use  RasterIOEx for all raster IO operations
- Add support for more C# raster IO data types
- Add C# default parameters
Extend StringListMarshal to support collections of KeyValuePair<string,string>
- Array out typemap was incorrect. It didn't free the array and didn't correctly marshal it.
- Add GetDefaultHistogramEx with ulong array
- Fix AdviseRead C# - buf_xsize and buf_ysize  were incorrectly mapped to type 'ref int' which can never be null in C#
- Allow passing multiple layers
- Add GDALProgressFunc typemap
Adjust GetNextFeature() definition to allow default arguments
- Use multivalue typemaps
- Add GetHistogramEx support
Also fix Checksum default argument
- Simplified and consolidated C# typemaps
- Expand TransformPoints methods to accept optional arrays
- Enable Geometry.ExportToWkb and Osr. CreateGeometryFromWkb to for geometries > 2GB (unmanaged data only)
- Expose Geometry.ExportToIsoWkb
- Expose SetDefaultHistogramEx
- Add more obsolete messages
Updated migration guide to reflect changes impacting C# users, including removed call sites and parameter type corrections.
@Mbucari

Mbucari commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

@rouault I fixed the typo causing the check to fail. The Ubuntu ASAN test always fails, but that doesn't appear to be caused by this PR.

@github-actions

Copy link
Copy Markdown

The GDAL project highly values your contribution and would love to see this work merged! Unfortunately this PR has not had any activity in the last 28 days and is being automatically marked as "stale". If you think this pull request should be merged, please check

  • that all unit tests are passing

  • that all comments by reviewers have been addressed

  • that there is enough information for reviewers, in particular link
    to any issues which this pull request fixes

  • that you have written unit tests where possible
    In case you should have any uncertainty, please leave a comment and we will be happy to help you proceed with this pull request.
    If there is no further activity on this pull request, it will be closed in 2 weeks.

@Mbucari

Mbucari commented Oct 21, 2026

Copy link
Copy Markdown
Contributor Author

This PR is ready for review. @runette

@github-actions github-actions Bot removed the stale label Oct 22, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants