[Gdal-dev] C# Bindings

Tamas Szekeres szekerest at gmail.com
Fri Nov 3 19:07:03 EST 2006


> >
> > I'm afraid we will not be able to map pointers to the C# interface
> > easily.
>
> Is this a SWIG limitation? Pointers are a valid C# type though, aren't they?
>

I mean that the C style pointers has no exact mapping to C# we have to
use the untyped IntPtr-s or HandleRef-s instead.


> Let's say you want to do the simplest thing: use GDAL to read RGB data
> from a file, stick it into an image and then display that image. Off the
> top of my head, one way of doing this (starting with a GDAL dataset
> object) would look something like:
>
> {
>   ...
>
>   // Get the GDAL Band objects from the Dataset
>   Gdal.Band redBand = dataset.GetRasterBand(1);
>   Gdal.Band greenBand = dataset.GetRasterBand(2);
>   Gdal.Band blueBand = dataset.GetRasterBand(3);
>
>   // Get the width and height of the Dataset
>   int width = dataset.RasterXSize;
>   int height = dataset.RasterYSize;
>
>   // Create a Bitmap to store the GDAL image in
>   Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
>
>   // Use GDAL raster reading methods to read the image data directly
> into the Bitmap
>   BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width,
> height),
>        ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
>   try {
>     int stride = bitmapData.Stride;
>     byte* buf = (byte*)bitmapData.Scan0.ToPointer();
>     // ReadRaster() here takes a byte* argument for the data pointer
>     redBand.ReadRaster(0, 0, width, height, buf, width, height, 3, stride);
>     greenBand.ReadRaster(0, 0, width, height, buf+1, width, height, 3,
> stride);
>     blueBand.ReadRaster(0, 0, width, height, buf+2, width, height, 3,
> stride);
>   }
>   finally {
>     bitmap.UnlockBits(bitmapData);
>   }
>
>   // Display the image by putting it into a PictureBox
>   pictureBox.Image = bitmap;
>
>   ...
> }
>
>
> If ReadRaster() took a byte[] rather than a byte* as an argument, then
> you would have to use GDAL to copy the band data first into a byte[]
> array, and then from there use InteropServices.Marshal.Copy() to copy
> the data into the Bitmap, which is inefficient in time and memory.
>
> If you do want to read into an array, then you can do something like:
>
>   byte[] buffer = new byte[width * height];
>   fixed (byte* ptr = buffer) {
>     band.ReadRaster(0, 0, width, height, ptr, width, height, 1, width);
>   }
>
> However, if the functions are setup to read directly into arrays, then
> I'm not sure how one could read data from GDAL directly into a Bitmap,
> where the buffer is only accessible via a pointer.
>
> As a compromise, how about we have a high and a low level interface? So
> you can have type safe versions with byte[], int[] etc, and low level
> versions that use an IntPtr and an argument specifying the  data type. We
> could call the lower level version RasterIO to correspond to the C
> function in GDAL.
>

Well, with the example above I am curious to know how if works in
practice. So as to support this kind of usage we gonna have to
establish a generic version of the ReadRaster/WriteRaster having
IntPtr compatible argument holding the memory to be handled at the
unmanaged part of the interface. It would be useful to know how
LockBits and Scan0 works, will the managed memory segment be prevented
from the relocation or GC collection during the unmanaged call. I will
create a sample app. for testing this issue.

BTW, I wonder how we can get the byte* notation work in general. Is it
related to an unsafe code block specification?

>
> > I have no problem about the number of the overloads. It would be more
> > important to keep
> > the interface obvious and clear.
> > We have no one by one mapping between the C++ and C# blittable types.
> > For a mapping table see for example the blittable types section at:
> > http://www.mono-project.com/Interop_with_Native_Libraries
>
> OK. FWIW, I imagine that 99.9% of people's needs can be addressed by
> overloads for the data types byte, short, ushort, int, uint and float.
>

I think we should support the generic functions first. If it works, we
will create the specializations using Marshal.Copy and calling the
generic fn-s internally.

> >
> > How could we restrict the usage of the templates to the array of the
> > simple blittable types?
> > However in the future it might be an option but now it's supported
> > only by MS.NET FW 2.0 AFAIK.
>
> In order to work with the underlying GDAL code you would need to turn
> the type into a GDAL type flag, so you could throw a runtime exception
> if an invalid type is used.
>

I hope we shall not have to bring  GDALRWFlag and GDALDataType into
the C# interface if it is possible.


I would like to get something working this weekend.

Best Regards,

Tamas


PS: Thanks, for your efforts about the manifest embedding stuff  :-)



More information about the Gdal-dev mailing list