[Gdal-dev] C# Bindings
Simon Perkins
sy at perkins.net
Fri Nov 3 21:19:05 EST 2006
Tamas Szekeres wrote:
>> >
>> > 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.
I don't know how SWIG works at all, but if we implement one low level
function that, say, uses IntPtr and a GDALDataType flag, then we can add
all the type safe versions as forwarding functions, e.g.:
private void ReadRasterImp(int xOff, int yOff, int xSize, int ySize,
IntPtr buf,
int bufXsize, int bufYSize, GDALDataType type) {
// Call GDAL external function directly
....
}
public void ReadRaster(int xOff, int yOff, int xSize, int ySize, byte*
buf, int bufXSize, int bufYSize) {
ReadRasterImp(xOff, yOff, xSize, ySize, new IntPtr(buf), bufXSize,
bufYSize, GDALDataType.BYTE);
}
public void ReadRaster(int xOff, int yOff, int xSize, int ySize, byte[]
buf, int bufXSize, int bufYSize) {
fixed (byte* ptr = buf) {
ReadRaster(xOff, yOff, xSize, ySize, ptr, bufXSize, bufYSize,
GDALDataType.BYTE);
}
}
I've omitted the pixelSpace and lineSpace args here.
Is that kind of thing doable with SWIG?
Couple of other questions / requests:
- For any functions that use an array as a buffer, it would be
convenient to add a bufferOffset int argument that says at what point in
the buffer reading/writing should begin. This allows people to use GDAL
to read into arrays that contain pixels in "packed" format. This only
needs to appear in the overload of these functions that has the
pixelSpace and lineSpace args, since packed format buffers require these
to be specified as well.
- How are we dealing with errors? The original GDAL functions return
CPLErr. Are we going to do the same? Or are we going to throw exceptions?
> 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?
The LockBits function must be called to prevent the GC moving the Bitmap
buffer while you're working on it. See the MSDN docs on
Bitmap.LockBits() for an example of usage.
Scan0 is simply an IntPtr that points to the start of the Bitmap data
buffer.
Not sure I understand your last question. In general, you can only use
pointers within a fixed() { } block, since that's the only safe way you
can get a pointer to a managed object. The fixed() statement prevents
the GC moving the object being pointed to. Needless to say, anything
using pointers has to be declared unsafe. But I think it's hard to avoid
that when interfaceing to unmanaged code that manipulates memory.
In case it helps, I've attached the hand-rolled GDAL C# interface that I
worked on a while back, along with a simple image display program that
uses that interface. You should just be able to unzip the file, load it
into VS 2005, edit the file GDAL/Interop.cs to reflect the name of the
GDAL DLL installed on your machine (make sure the DLL has the manifests
embedded or you'll get DLL loading errors!), build the solution, ensure
that the GDAL DLL is on your PATH, and then hit F5 to run the test
program. Go to File->Open... and load any image...
This might clarify some of the locking / unlocking / Interop issues.
Note that this code implements RasterIO following the GDAL pattern very
closely, so it's probably lower level than what you want to do.
> 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.
When you say "generic", I'm guessing you're not using it in the sense of
"C# generics" (AKA C# templates)? That's the sense I've been using it in
my e-mails... Not exactly sure what you have in mind here, but I'd
prefer to avoid uncecessary copies of data if possible. I use GDAL to
access some very large rasters, and so efficiency is important to me.
> I hope we shall not have to bring GDALRWFlag and GDALDataType into
> the C# interface if it is possible.
Agreed.
> I would like to get something working this weekend.
Groovy.
> PS: Thanks, for your efforts about the manifest embedding stuff :-)
No problem - the only tricky thing is finding decent documentation from
Microsoft on any of this stuff...
Cheers,
Sy
More information about the Gdal-dev
mailing list