Function-specific Typemaps (with C#)

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Function-specific Typemaps (with C#)

Wes Hodges
hey,
 
please ignore my previous post if there is one - it accidently got sent before i was through.
 
i have a followup question to what Norman was asking earlier (see [Swig] C# garbage collection) and the extremely helpful documentation at http://cvs.sourceforge.net/viewcvs.py/*checkout*/swig/SWIG/Doc/Manual/CSharp.html:
 
in the example at the bottom of the doc, the following 'csin' typemap is given:
 
%typemap(csin) Element *e "getCPtrAndAddReference($csinput)"
 
so, as far as i can tell from what i've read and what i've tried in my code is that this targets *any* function arguments named 'e' and are Element pointers, essentially replacing getCPtr(e) with getCPtrAndAddReference(e).  is there a way to make the typemap function specific (i.e. just swap the Element *e argument in *one* particular function, and ignore the rest)?  i've been reading through the docs for a while now, and can't really zero in on anything.  i was hoping the typemaps modifiers may provide a solution, but, it doesn't appear that way.
 
to illustrate what i'm trying to do, consider extending the C++ Container class in the doc example i mentioned earlier to store a vector of Elements.  add the following class members:
 
class Container
{
   ...
 
   std::vector<Element*> elements;
 
   void addElement(Element *e) { // Code to add e to 'elements' }
   void removeElement(Element *e) { // Code to remove e to 'elements' }
 
   ...
};
 
and let's extend the 'cscode' typemap:
 
%typemap(cscode) Container %{
  // Ensure that the GC doesn't collect any Element added from C#
  // as the underlying C++ class stores a shallow copy
  private System.Collections.ArrayList elementReferences;        // Changed to an ArrayList of Element references
  private HandleRef getCPtrAndAddReference(Element element) {
    elementReferences.Add(element);
    return Element.getCPtr(element);
  private HandleRef getCPtrAndRemoveReference(Element element) {
    elementReferences.Remove(element);
    return Element.getCPtr(element);
  }
%}
 
ok.  so, when i call Container.addElement, i want the getCPtrAndAddReference code to get executed, and when i call Container.removeElement, i was the getCPtrAndRemoveReference code executed.  unfortunately, this 'csin' typemap:
 
%typemap(csin) Element *e "getCPtrAndAddReference($csinput)"
 
will swap *all* 'Element *e' arguments with getCPtrAndAddReference, meaning removeElement will execute getCPtrAndAddReference, not getCPtrAndRemoveReference.  is there a way that i can modify the 'csin' typemap to only affect certain function(s)?  something like this (and, yes, i know this code won't work):
 
%typemap(csin, function = "addElement") Element *e "getCPtrAndAddReference($csinput)"   // Only maps to addElement(Element *e)
%typemap(csin, function = "removeElement") Element *e "getCPtrAndRemoveReference($csinput)"   // Only maps to removeElement(Element *e)
 
Wes
 
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Function-specific Typemaps (with C#)

William S Fulton
Wes Hodges wrote:

> hey,
>  
> please ignore my previous post if there is one - it accidently got sent
> before i was through.
>  
> i have a followup question to what Norman was asking earlier (see [Swig]
> C# garbage collection) and the extremely helpful documentation at
> http://cvs.sourceforge.net/viewcvs.py/*checkout*/swig/SWIG/Doc/Manual/CSharp.html:
>  
> in the example at the bottom of the doc, the following 'csin' typemap is
> given:
>  
> %typemap(csin) Element *e "getCPtrAndAddReference($csinput)"
>  
> so, as far as i can tell from what i've read and what i've tried in my
> code is that this targets *any* function arguments named 'e' and are
> Element pointers, essentially replacing getCPtr(e) with
> getCPtrAndAddReference(e).  is there a way to make the typemap function
> specific (i.e. just swap the Element *e argument in *one* particular
> function, and ignore the rest)?  i've been reading through the docs for
> a while now, and can't really zero in on anything.  i was hoping the
> typemaps modifiers may provide a solution, but, it doesn't appear that way.
>  
> to illustrate what i'm trying to do, consider extending the C++
> Container class in the doc example i mentioned earlier to store a vector
> of Elements.  add the following class members:
>  
> class Container
> {
>    ...
>  
>    std::vector<Element*> elements;
>  
>    void addElement(Element *e) { // Code to add e to 'elements' }
>    void removeElement(Element *e) { // Code to remove e to 'elements' }
>  
>    ...
> };
>  
> and let's extend the 'cscode' typemap:
>  
> %typemap(cscode) Container %{
>   // Ensure that the GC doesn't collect any Element added from C#
>   // as the underlying C++ class stores a shallow copy
>   private System.Collections.ArrayList elementReferences;        //
> Changed to an ArrayList of Element references
>   private HandleRef getCPtrAndAddReference(Element element) {
>     elementReferences.Add(element);
>     return Element.getCPtr(element);
>   private HandleRef getCPtrAndRemoveReference(Element element) {
>     elementReferences.Remove(element);
>     return Element.getCPtr(element);
>   }
> %}
>  
> ok.  so, when i call Container.addElement, i want the
> getCPtrAndAddReference code to get executed, and when i call
> Container.removeElement, i was the getCPtrAndRemoveReference code
> executed.  unfortunately, this 'csin' typemap:
>  
> %typemap(csin) Element *e "getCPtrAndAddReference($csinput)"
>  
> will swap *all* 'Element *e' arguments with getCPtrAndAddReference,
> meaning removeElement will execute getCPtrAndAddReference, not
> getCPtrAndRemoveReference.  is there a way that i can modify the 'csin'
> typemap to only affect certain function(s)?  something like this (and,
> yes, i know this code won't work):
>  
> %typemap(csin, function = "addElement") Element *e
> "getCPtrAndAddReference($csinput)"   // Only maps to addElement(Element *e)
> %typemap(csin, function = "removeElement") Element *e
> "getCPtrAndRemoveReference($csinput)"   // Only maps to
> removeElement(Element *e)
>  
I'm afraid there is no neat way other than renaming the variable. I will
shortly be adding in a feature so that you can completely replace the
generated proxy function. Until then there are a couple of solutions:

1) Rename the generated proxy function (also good idea to make it
private) and manually add in the version you want in the proxy class...

%typemap(cscode) Container %{
   ...
   public void removeElement(Element e) {
     $modulePINVOKE.Container__removeElement(swigCPtr,
getCPtrAndRemoveReference(e));
   }
%}

// Rename the proxy call
%rename (_removeElement) Container::removeElement;
// Make the proxy call private
// It basically becomes redundant
%csmethodmodifiers Container::removeElement "private";

2)
// Ignore the original method
%ignore Container::removeElement;

// Typemap for the renamed parameter
%typemap(csin) Element *elementToRemove
"getCPtrAndRemoveReference($csinput)"

// Add in a method which just forwards the call on to the original
// method (but has a different parameter name)
%extend Container {
   void deleteElement(Element *elementToRemove) {
     self->removeElement(remove_element);
   }
}

For 2) you could even keep the original method name 'removeElement' if
you use %rename and are careful about the order of the %extend and %rename.

William


-------------------------------------------------------
SF.Net email is sponsored by:
Tame your development challenges with Apache's Geronimo App Server. Download
it for free - -and be entered to win a 42" plasma tv or your very own
Sony(tm)PSP.  Click here to play: http://sourceforge.net/geronimo.php
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Loading...