[Swig] C# garbage collection

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

[Swig] C# garbage collection

Norman Young
Hi,

I've created a C# wrapper for a C++ DLL.  I've got a couple of proxy
classes like this:

MyProxyClass
MyProxyCollectionClass

Then, I have code like this:

class MyClass
{
  private MyProxyCollectionClass _ObjectCollection;

  public MyClass()
  {
     MyProxyClass obj = new MyProxyClass ();
     _ObjectCollection.Add(obj);
  }
}

Eventually (and unfortunately) obj gets garbage collected since no
reference to it exists in managed code, causing all sorts of problems.
 (If obj is changed to a member variable of MyClass, the problem is
solved, since the reference to it remains in managed code and
preventing garbage colleciton.)  So, a couple of questions:

1) Was 1.3.25 supposed to prevent this type of early garbage collection?
2) If not, then what might be the best way to prevent obj from being destroyed?

Thanks!

Norman


-------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Swig] C# garbage collection

William S Fulton
Norman Young wrote:

> Hi,
>
> I've created a C# wrapper for a C++ DLL.  I've got a couple of proxy
> classes like this:
>
> MyProxyClass
> MyProxyCollectionClass
>
> Then, I have code like this:
>
> class MyClass
> {
>   private MyProxyCollectionClass _ObjectCollection;
>
>   public MyClass()
>   {
>      MyProxyClass obj = new MyProxyClass ();
>      _ObjectCollection.Add(obj);
>   }
> }
>
> Eventually (and unfortunately) obj gets garbage collected since no
> reference to it exists in managed code, causing all sorts of problems.
>  (If obj is changed to a member variable of MyClass, the problem is
> solved, since the reference to it remains in managed code and
> preventing garbage colleciton.)  So, a couple of questions:
>
> 1) Was 1.3.25 supposed to prevent this type of early garbage collection?
> 2) If not, then what might be the best way to prevent obj from being destroyed?
>

SWIG can never detect that there is a reference which must be kept
alive, so manual intervention is required. I either make that reference
in the C# side, 'teaching' the garbage collector the real references.
Otherwise, when you add the obj into _ObjectCollection, set the obj's
swigCMemOwn flag to false. Then your _ObjectCollection must manage the
lifetime of obj. You can do all this with the C# typemaps. Alternatively
store the objects by value rather than references or pointers in the
collection.

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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Swig] C# garbage collection

Norman Young
Thanks for such a quick reply.  Just a couple of followup questions:

1) Could you clarify (perhaps an example?) what you mean by "teaching"
the garbage collector what the real references are?  Do you mean just
keeping references in a list or something?

2) With respect to the solution involving the swigCMemOwn flag, would
I basically just create a new typemap that generates constructor code
with the flag set to false for the proxy classes I want to keep
around?

N.

On 02/11/05, William S Fulton <[hidden email]> wrote:

> Norman Young wrote:
> > Hi,
> >
> > I've created a C# wrapper for a C++ DLL.  I've got a couple of proxy
> > classes like this:
> >
> > MyProxyClass
> > MyProxyCollectionClass
> >
> > Then, I have code like this:
> >
> > class MyClass
> > {
> >   private MyProxyCollectionClass _ObjectCollection;
> >
> >   public MyClass()
> >   {
> >      MyProxyClass obj = new MyProxyClass ();
> >      _ObjectCollection.Add(obj);
> >   }
> > }
> >
> > Eventually (and unfortunately) obj gets garbage collected since no
> > reference to it exists in managed code, causing all sorts of problems.
> >  (If obj is changed to a member variable of MyClass, the problem is
> > solved, since the reference to it remains in managed code and
> > preventing garbage colleciton.)  So, a couple of questions:
> >
> > 1) Was 1.3.25 supposed to prevent this type of early garbage collection?
> > 2) If not, then what might be the best way to prevent obj from being destroyed?
> >
>
> SWIG can never detect that there is a reference which must be kept
> alive, so manual intervention is required. I either make that reference
> in the C# side, 'teaching' the garbage collector the real references.
> Otherwise, when you add the obj into _ObjectCollection, set the obj's
> swigCMemOwn flag to false. Then your _ObjectCollection must manage the
> lifetime of obj. You can do all this with the C# typemaps. Alternatively
> store the objects by value rather than references or pointers in the
> collection.
>
> 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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Swig] C# garbage collection

William S Fulton
Norman Young wrote:
> Thanks for such a quick reply.  Just a couple of followup questions:
>
> 1) Could you clarify (perhaps an example?) what you mean by "teaching"
> the garbage collector what the real references are?  Do you mean just
> keeping references in a list or something?
>
Example code below. I've got Java and C# versions lying around so have
included both for general consumption. If you uncomment the use of the
%call_get_cptr_and_add_reference and
%add_get_cptr_and_add_reference_method
macros and run this code:

       Container container = new Container();
       Element element = new Element(20);
       container.setElement(element);
       Console.WriteLine("element.value: " + container.getElement().value);
       System.GC.Collect();
       System.GC.WaitForPendingFinalizers();
       Console.WriteLine("element.value: " + container.getElement().value);

You will see the second time that 'value' is printed it is duff, whereas
if the typemaps in the macros are used, the gc has been 'taught' about
the references.

Since drafting this email I've added in examples to the documentation
(Java and C#) covering this situation and accessing pointers/references
to member variables. You should be able to view it later on
today/tomorrow at
http://cvs.sourceforge.net/viewcvs.py/*checkout*/swig/SWIG/Doc/Manual/CSharp.html: 
two new memory management typemap examples at the end.

 > 2) With respect to the solution involving the swigCMemOwn flag, would
 > I basically just create a new typemap that generates constructor code
 > with the flag set to false for the proxy classes I want to keep
 > around?
I'd just use the 'javacode' typemap to add in a public method to
set/unset the flag, then call it appropriately from your code.

William

////////////////////////////////////////////////////////////////////////////////
%define %call_get_cptr_and_add_reference(REFCLASS)
#if defined(SWIGJAVA)
%typemap(javain) REFCLASS "getCPtrAndAddReference($javainput)"
#elif defined(SWIGCSHARP)
%typemap(csin) REFCLASS "getCPtrAndAddReference($csinput)"
#endif
%enddef

////////////////////////////////////////////////////////////////////////////////
%define %add_get_cptr_and_add_reference_method(CLASSNAME, REFCLASS, REFNAME)
#if defined(SWIGJAVA)
%typemap(javacode) CLASSNAME %{
   // Ensure that the GC doesn't collect any REFNAME set from Java as
the underlying C++ class stores a shallow copy
   private REFCLASS REFNAME##Reference;
   private long getCPtrAndAddReference(REFCLASS REFNAME) {
     REFNAME##Reference = REFNAME;
     return REFCLASS.getCPtr(REFNAME);
   }
%}
#elif defined(SWIGCSHARP)
%typemap(cscode) CLASSNAME %{
   // Ensure that the GC doesn't collect any REFNAME set from C# as the
underlying C++ class stores a shallow copy
   private REFCLASS REFNAME##Reference;
   private HandleRef getCPtrAndAddReference(REFCLASS REFNAME) {
     REFNAME##Reference = REFNAME;
     return REFCLASS.getCPtr(REFNAME);
   }
%}
#endif
%enddef

%call_get_cptr_and_add_reference(Element *e)
%add_get_cptr_and_add_reference_method(Container, Element, element)

%inline %{
struct Element {
   int value;
   Element(int val) : value(val) {}
};
class Container {
   Element* element;
public:
   Container() : element(0) {}
   void setElement(Element* e) { element = e; }
   Element* getElement() { return element; }
};
%}



-------------------------------------------------------
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
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [Swig] C# garbage collection

Norman Young
Thanks--the addendum to the documentation is great!  Very helpful.

Norman

On 04/11/05, William S Fulton <[hidden email]> wrote:

> Norman Young wrote:
> > Thanks for such a quick reply.  Just a couple of followup questions:
> >
> > 1) Could you clarify (perhaps an example?) what you mean by "teaching"
> > the garbage collector what the real references are?  Do you mean just
> > keeping references in a list or something?
> >
> Example code below. I've got Java and C# versions lying around so have
> included both for general consumption. If you uncomment the use of the
> %call_get_cptr_and_add_reference and
> %add_get_cptr_and_add_reference_method
> macros and run this code:
>
>        Container container = new Container();
>        Element element = new Element(20);
>        container.setElement(element);
>        Console.WriteLine("element.value: " + container.getElement().value);
>        System.GC.Collect();
>        System.GC.WaitForPendingFinalizers();
>        Console.WriteLine("element.value: " + container.getElement().value);
>
> You will see the second time that 'value' is printed it is duff, whereas
> if the typemaps in the macros are used, the gc has been 'taught' about
> the references.
>
> Since drafting this email I've added in examples to the documentation
> (Java and C#) covering this situation and accessing pointers/references
> to member variables. You should be able to view it later on
> today/tomorrow at
> http://cvs.sourceforge.net/viewcvs.py/*checkout*/swig/SWIG/Doc/Manual/CSharp.html:
> two new memory management typemap examples at the end.
>
>  > 2) With respect to the solution involving the swigCMemOwn flag, would
>  > I basically just create a new typemap that generates constructor code
>  > with the flag set to false for the proxy classes I want to keep
>  > around?
> I'd just use the 'javacode' typemap to add in a public method to
> set/unset the flag, then call it appropriately from your code.
>
> William
>
> ////////////////////////////////////////////////////////////////////////////////
> %define %call_get_cptr_and_add_reference(REFCLASS)
> #if defined(SWIGJAVA)
> %typemap(javain) REFCLASS "getCPtrAndAddReference($javainput)"
> #elif defined(SWIGCSHARP)
> %typemap(csin) REFCLASS "getCPtrAndAddReference($csinput)"
> #endif
> %enddef
>
> ////////////////////////////////////////////////////////////////////////////////
> %define %add_get_cptr_and_add_reference_method(CLASSNAME, REFCLASS, REFNAME)
> #if defined(SWIGJAVA)
> %typemap(javacode) CLASSNAME %{
>    // Ensure that the GC doesn't collect any REFNAME set from Java as
> the underlying C++ class stores a shallow copy
>    private REFCLASS REFNAME##Reference;
>    private long getCPtrAndAddReference(REFCLASS REFNAME) {
>      REFNAME##Reference = REFNAME;
>      return REFCLASS.getCPtr(REFNAME);
>    }
> %}
> #elif defined(SWIGCSHARP)
> %typemap(cscode) CLASSNAME %{
>    // Ensure that the GC doesn't collect any REFNAME set from C# as the
> underlying C++ class stores a shallow copy
>    private REFCLASS REFNAME##Reference;
>    private HandleRef getCPtrAndAddReference(REFCLASS REFNAME) {
>      REFNAME##Reference = REFNAME;
>      return REFCLASS.getCPtr(REFNAME);
>    }
> %}
> #endif
> %enddef
>
> %call_get_cptr_and_add_reference(Element *e)
> %add_get_cptr_and_add_reference_method(Container, Element, element)
>
> %inline %{
> struct Element {
>    int value;
>    Element(int val) : value(val) {}
> };
> class Container {
>    Element* element;
> public:
>    Container() : element(0) {}
>    void setElement(Element* e) { element = e; }
>    Element* getElement() { return element; }
> };
> %}
>
>


-------------------------------------------------------
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...