In SWIG-C# at least, I use %feature(unref) (but not %feature(ref)) and some typemaps to achieve refcounting.

 

My C# counted_obj macro assumes your class has methods “AddRef” and “ReleaseRef”. Change it to your liking.

 

Usage: %counted_obj(ClassName)

 

If you are wrapping a class hierarchy, you must use %counted_obj on all classes in the hierarchy, otherwise the code will malfunction because %feature(unref) applies to all classes in a hierarchy but the typemaps do not.

 

////////////////////////////////////////////////////////////////////////////////

// Adds support for reference counting the specified type, assuming that the

// type includes AddRef() and ReleaseRef() methods. Unfortunately, this must

// be applied to every class in a class hierarchy. Also, this macro changes

// many typemaps, and it may be incompatible with other macros that change

// the same typemaps.

%define %counted_obj(TYPE)

       // The 'ref' and 'unref' features enable reference counting on 'new' and

       // 'delete' only (in C#, delete is called for garbage collection.) These

       // are nice features because they apply to a whole type hierarchy.

       // Unfortunately, they are not enough. The refcount must be incremented

       // whenever a function returns TYPE*, so we use the 'out' typemap to

       // accomplish that. Since the 'out' typemap applies to the 'new' operator,

       // we cannot use 'ref' to add a reference at the same time, for it would

       // cause a second increment. Unfortunately, typemaps do not apply to

       // entire hierarchies, which is why %counted_obj must be used on every

       // class in a hierarchy.

       %feature("unref") TYPE "$this->ReleaseRef(); // unref"

       %typemap(csin) TYPE "$csinput.Ptr"

      

       %typemap(in)       TYPE* %{ $1 = (TYPE*)$input; %}

       %typemap(varin)    TYPE* %{ $1 = (TYPE*)$input; %}

       //%typemap(memberin) TYPE* %{ $1 = (TYPE*)$input; %}

       %typemap(out, null="NULL") TYPE* %{

              if ($1 != NULL) $1->AddRef(); // C# side is responsible for releasing the reference

              $result = $1;

       %}

       %typemap(csout, excode=SWIGEXCODE) TYPE* {

              IntPtr cPtr = $imcall;$excode

              if (cPtr == IntPtr.Zero)

                return null;

              //GC.KeepAlive(this);

              return new $csclassname(cPtr, true);

         }

       %typemap(csvarout, excode=SWIGEXCODE2) TYPE* %{

              get {

                IntPtr cPtr = $imcall;$excode

                if (cPtr == IntPtr.Zero)

                  return null;

                //GC.KeepAlive(this);

                return new $csclassname(cPtr, true);

              } %}

%enddef

 

 

From: Tom Yaxley [mailto:tommitytom@gmail.com]
Sent: Sunday, October 24, 2010 8:23 AM
To: swig-user@lists.sourceforge.net
Subject: [Swig-user] Handling a C++ objects reference count in the proxy class

 

I was wondering if it was possible to insert code in to the wrapper so it would look similar to this:

 

SWIGEXPORT void * SWIGSTDCALL CSharp_new_MyClass() {

          void * jresult ;

          MyClass *result = 0 ;

 

          result = (MyClass *)new MyClass();

 

        result->IncrRefCount(); // Increase the reference count of this object

 

          jresult = (void *)result; 

          return jresult;

}

 

... since I'd like the proxy class to handle it's own reference count rather than have to wrap my SmartPtr, which I'd rather be only used in C++ code.

 

Cheers,

Tom