/** * refcount.i * * Common refcounting module applicable for all language targets */ // SWIG is refcounting aware and since our C++ classes follow a refcounting scheme // we can tap into this feature // // NOTE: We don't implement %feature("ref") because anything from the native boundary is already AddRef'd and the // ref feature assumes refcounted objects that were just instantiated start off with a reference count of 0, ours // start at 1. (based from their refcounting example: https://swig.org/Doc4.0/SWIGDocumentation.html#SWIGPlus_ref_unref) // // All the managed layer should do when Disposed or GC'd is to make sure it is released %feature("ref") MgDisposable "" %feature("unref") MgDisposable "ReleaseObject($this);" %runtime %{ #include "Foundation.h" #if defined(REFCOUNTING_DIAGNOSTICS) INT32 NewObjectHook(MgDisposable* obj) { if (NULL != obj) { INT32 rc = obj->GetRefCount(); #if defined(SWIGPHP) zend_printf("[zend]: New instance of (%s): %p - %d\n", obj->GetMultiByteClassName(), (void*)obj, rc); #else printf("[native]: New instance of (%s): %p - %d\n", obj->GetMultiByteClassName(), (void*)obj, rc); #endif return rc; } return -1; } INT32 RefCountHook(MgDisposable* obj) { if (NULL != obj) { INT32 rc = obj->GetRefCount(); #if defined(SWIGPHP) zend_printf("[zend]: Ref-count for instance of (%s): %p - %d\n", obj->GetMultiByteClassName(), (void*)obj, rc); #else printf("[native]: Ref-count for instance of (%s): %p - %d\n", obj->GetMultiByteClassName(), (void*)obj, rc); #endif return rc; } return -1; } void ReleaseObject(MgDisposable* obj) { if (NULL != obj) { INT32 rc = obj->GetRefCount(); #if defined(SWIGPHP) zend_printf("[zend]: Releasing instance of (%s): %p (%d -> %d)\n", obj->GetMultiByteClassName(), (void*)obj, rc, rc - 1); #else printf("[native]: Releasing instance of (%s): %p (%d -> %d)\n", obj->GetMultiByteClassName(), (void*)obj, rc, rc - 1); #endif } SAFE_RELEASE(obj); } #else #define NewObjectHook(obj) #define RefCountHook(obj) void ReleaseObject(MgDisposable* obj) { SAFE_RELEASE(obj); } #endif %}