SWIG and CSharp

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

SWIG and CSharp

Frank Warmerdam
Kevin,

I have plunged into the world of SWIG, and with my choice of
CSharp I seem to have picked the deep end. :-)

I spent some time this weekend playing with calling GDAL from
C# as part of my long delayed committment to actually help a
bit on the SWIG wrappers - and to figure out what we can do from
.net languages.

I have made a few modest changes:
 o csharp makefile.vc now set the right -dllimport name.
    Before the dll name being searched for was "gdal.dll"
    instead of "gdal_gdal_wrap.dll".

 o the makefile now builds the c# proxy classes with debug
   so I can get a bit more visibility into what is happening.  It
   would be cool if I could debug right through the PInvokes into
   the DLL but I haven't figured out how to do that.

 o I have implemented typemaps for "double *" and "double arg[ANY]"
    that seem good enough that stuff like GetGeoTransform(),
    and SetGeoTransform() are now working.  I just map it to a double[]
    in c#.  Currently I don't think this distinguishes the case where a
    pointer to a single double is used to return values so there may be
    more work to do.   Also, there is no array size checking, so if
    the app passes too small a c# array memory will get corrupted.

 o I am working on passing buffers for ReadRaster() and WriteRaster().
    I have the WriteRaster case on the dataset working (I think) with
    the following magic:

%typemap(ctype)  (int buf_len, char *buf_string) "int, char *"
%typemap(imtype) (int buf_len, char *buf_string) "int buf_len, byte[]"
%typemap(cstype) (int buf_len, char *buf_string) "byte[]"
%typemap(csin)   (int buf_len, char *buf_string) "$csinput.Length, $csinput"

    I have used the specific names of the arguments in the hope to
    restrict it to the case of buffers with a length being passed in to
    stuff like WriteRaster().  This now applies to Dataset.WriteRaster(),
    but not too Band.WriteRaster().  Would it be ok for me to change
    Band.i to use the exact same argument names for buf_len and buf_string
    as Dataset.i?   I forsee some other specific naming conventions being
    needed for some other cases that I want to handle pretty specially  in
    c#.  Other than obvious special names like argin and argout how much
    dependence is there on argument names in the .i files?

There are still lots of mappings left to do, but I would like to at least
get the point where I can do various GDAL operations, and then review
OGR after that.

I have been able to open datasets, get back stuff like their size,
projection and now geotransform.  I haven't gotten much further than
that.

Best regards,
--
---------------------------------------+--------------------------------------
I set the clouds in motion - turn up   | Frank Warmerdam, [hidden email]
light and sound - activate the windows | http://pobox.com/~warmerdam
and watch the world go round - Rush    | Geospatial Programmer for Rent

_______________________________________________
Gdal-dev mailing list
[hidden email]
http://lists.maptools.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: SWIG and CSharp

Ari Jolma
Frank Warmerdam wrote:

>    but not too Band.WriteRaster().  Would it be ok for me to change
>    Band.i to use the exact same argument names for buf_len and buf_string
>    as Dataset.i?   I forsee some other specific naming conventions being
>    needed for some other cases that I want to handle pretty specially  in
>    c#.  Other than obvious special names like argin and argout how much
>    dependence is there on argument names in the .i files?
>  
>

Nothing I believe. Typemaps are written for _type_ patterns. argin and
argout in typemaps are just conventions. I may be wrong of course.
Kevin, please correct me if I am.

Ari

--
Prof. Ari Jolma
Kartografia ja Geoinformatiikka / Cartography and Geoinformatics
Teknillinen Korkeakoulu / Helsinki University of Technology
POBox 1200, 02015 TKK, Finland
Email: ari.jolma at tkk.fi URL: http://www.tkk.fi/~jolma

_______________________________________________
Gdal-dev mailing list
[hidden email]
http://lists.maptools.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: SWIG and CSharp

Kevin Ruland
In reply to this post by Frank Warmerdam

Frank,

Welcome to the club!

Frank Warmerdam wrote:

>Kevin,
>
>I have plunged into the world of SWIG, and with my choice of
>CSharp I seem to have picked the deep end. :-)
>
>  
>
Yes, it's very deep.  There is a new SWIG 1.3.26rc1 out right now.  It
was cut from cvs a couple of days ago (Saturday, I think).  In any case
there have been changes to C# in 1.3.26 which might prove useful.  In
particular, they've fixed the naming of the setter/getter functions for
the member variables so we can remove the renamed setters/getters from
the gdal_cshap.i file.  What I mean, they use the same naming as the
python and the other generators.

My understanding of C# is it should be relatively easy to make these
typemaps because you don't have to do a bunch of magic to converts lists
to/from arrays etc.

> o I have implemented typemaps for "double *" and "double arg[ANY]"
>    that seem good enough that stuff like GetGeoTransform(),
>    and SetGeoTransform() are now working.  I just map it to a double[]
>    in c#.  Currently I don't think this distinguishes the case where a
>    pointer to a single double is used to return values so there may be
>    more work to do.   Also, there is no array size checking, so if
>    the app passes too small a c# array memory will get corrupted.
>
>  
>
There is a distinction made in the typemaps for return arguments and for
arrays. These are used for output arguments:

%typemap(in,numinputs=0) (double argout[ANY])
%typemap(argout) (double argout[ANY])

%typemaps(in,numinputs=0) (double *argout[ANY])
%typemaps(argout) (double *argout[ANY])
%typemap(freearg) (double *argout[ANY])

The grouping is intentional.  The 'in,numinputs=0' piece is used at the
top of the wrapper, the 'argout' is used to convert the returned value
from the wrapped method into whatever is really returned by the wrapper,
the 'freearg' is used to release memory allocated by the
'in,numinputs=0' typemap.

This one is used for input:

%typemap(in) (double argin[ANY])

These typemaps will match functions which have this kind of signature:

void funcout( double argout[14] )
void funcpout( double *argout[7] )
void funin( double argin[3] )

etc.  In particular, it requires the argument to be a fixed sized array.

There is only one typemap used for arbitrary double * parameters:

%typemap(xxx) (double *argout)

In the python bindings, we used the 'double *OUTPUT' typemap which comes
from the typemaps.i library.

There may or may not be a way to catch the small array problem.  In the
wrappers for the [ANY] types, you have access to the size required in
$dim0 (or $1_dim0 if you have more than one argument).  However, I don't
know if you have access to the size sent in from C#.

> o I am working on passing buffers for ReadRaster() and WriteRaster().
>    I have the WriteRaster case on the dataset working (I think) with
>    the following magic:
>
>%typemap(ctype)  (int buf_len, char *buf_string) "int, char *"
>%typemap(imtype) (int buf_len, char *buf_string) "int buf_len, byte[]"
>%typemap(cstype) (int buf_len, char *buf_string) "byte[]"
>%typemap(csin)   (int buf_len, char *buf_string) "$csinput.Length, $csinput"
>
>    I have used the specific names of the arguments in the hope to
>    restrict it to the case of buffers with a length being passed in to
>    stuff like WriteRaster().  This now applies to Dataset.WriteRaster(),
>    but not too Band.WriteRaster().  Would it be ok for me to change
>    Band.i to use the exact same argument names for buf_len and buf_string
>    as Dataset.i?   I forsee some other specific naming conventions being
>    needed for some other cases that I want to handle pretty specially  in
>    c#.  Other than obvious special names like argin and argout how much
>    dependence is there on argument names in the .i files?
>
>  
>
I think in your follow-up email you touched on this.  We used named
typemaps and use the %apply/%clear to make sure the proper typemap is
applied to each function.  I think was a reasonable solution which
provides complete control over which typemaps get applied although it is
a little more cumbersome.  You need to follow the typemap argument names
outlined in the README.typemaps file.  Those argument names are used in
the %apply commands.

I don't really know what the special c# typemaps are.  Here you've used
'ctype', 'imtype', 'cstype', 'csin'.  They are particular to C# wrapper
generation.  I hope they get used along with the 'in', 'out', 'argout'
typemaps when we use %apply.

>There are still lots of mappings left to do, but I would like to at least
>get the point where I can do various GDAL operations, and then review
>OGR after that.
>
>I have been able to open datasets, get back stuff like their size,
>projection and now geotransform.  I haven't gotten much further than
>that.
>
>  
>
That's further than before :)  One small step....

Kevin
_______________________________________________
Gdal-dev mailing list
[hidden email]
http://lists.maptools.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: SWIG and CSharp

Kevin Ruland
In reply to this post by Ari Jolma

Ari Jolma wrote:

> Frank Warmerdam wrote:
>
>>    but not too Band.WriteRaster().  Would it be ok for me to change
>>    Band.i to use the exact same argument names for buf_len and
>> buf_string
>>    as Dataset.i?   I forsee some other specific naming conventions being
>>    needed for some other cases that I want to handle pretty
>> specially  in
>>    c#.  Other than obvious special names like argin and argout how much
>>    dependence is there on argument names in the .i files?
>>  
>>
>
> Nothing I believe. Typemaps are written for _type_ patterns. argin and
> argout in typemaps are just conventions. I may be wrong of course.
> Kevin, please correct me if I am.
>
> Ari
>

Ari,

it works like this:

If you specify argument names in the typemap, then the typemap selection
process will match argument names in the wrapped functions.  If you
don't specify argument names in the typemap, then they are not used in
selection process.  Here's a simple example:

%typemap(in) (int specialname) "/* Using specialname */"
%typemap(in) (int) "/* Using general typemap */"

void func1( int avariable );
void func2( int specialname);

This will use the "general typemap" for argument 1 (avariable) of func1
and will use "specialname typemap" for argument 1 (specialname) of func2.

All of the typemaps which we've defined have argument names.  This
prevents them from being used unless they are intended.   There are many
times when we force a typemap to be used by using the %apply directive.

%apply (int specialname) { (int differentname) };
void func3 (int differentname);
%clear (int differentname);

This will use the "specialname" typemap for argument 1 of func3.  We use
%clear immediately afterwards, because %apply is global and will be used
from that point on otherwise.  Again, this is to prevent mis application
of typemaps.

There are problems with the "out" typemaps because returned values do
not have names in C delcs.  We've used two different tricks to get these
to apply correctly.  The latest is to leverage the fact that most
returned values are CPLErr or OGRErr which even though they are ints are
treated as different types in SWIG.  These typemaps actually apply globally.

Kevin
_______________________________________________
Gdal-dev mailing list
[hidden email]
http://lists.maptools.org/mailman/listinfo/gdal-dev
Reply | Threaded
Open this post in threaded view
|

Re: SWIG and CSharp

Ari Jolma
Kevin Ruland wrote:

>it works like this:
>
>If you specify argument names in the typemap, then the typemap selection
>process will match argument names in the wrapped functions.  If you
>don't specify argument names in the typemap, then they are not used in
>selection process.  Here's a simple example:
>
>%typemap(in) (int specialname) "/* Using specialname */"
>%typemap(in) (int) "/* Using general typemap */"
>  
>

ok, thanks for this, then they argument names matter very much, actually
it seems that it is easy to introduce strange bugs just by rename...

then I could write all those "undef not accepted" typemaps (given that
the argument names are different), which I already though was not possible

And I thought I almost had figured swig out...

Ari

--
Prof. Ari Jolma
Kartografia ja Geoinformatiikka / Cartography and Geoinformatics
Teknillinen Korkeakoulu / Helsinki University of Technology
POBox 1200, 02015 TKK, Finland
Email: ari.jolma at tkk.fi URL: http://www.tkk.fi/~jolma

_______________________________________________
Gdal-dev mailing list
[hidden email]
http://lists.maptools.org/mailman/listinfo/gdal-dev