From 657a0c9ac0a7083ce97f97a2e78dea927d3a1f78 Mon Sep 17 00:00:00 2001 From: Michael Giagnocavo Date: Thu, 2 Oct 2008 18:59:09 +0000 Subject: [PATCH] P/Invoke should do all the work for us git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9797 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/languages/mod_managed/freeswitch_managed.cpp | 12 +++++------- src/mod/languages/mod_managed/freeswitch_managed.h | 9 +++++---- .../languages/mod_managed/managed/ManagedSession.cs | 8 ++++++++ src/mod/languages/mod_managed/mod_managed.cpp | 7 +++---- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/mod/languages/mod_managed/freeswitch_managed.cpp b/src/mod/languages/mod_managed/freeswitch_managed.cpp index 119fb3a728..fe9d4dd381 100644 --- a/src/mod/languages/mod_managed/freeswitch_managed.cpp +++ b/src/mod/languages/mod_managed/freeswitch_managed.cpp @@ -74,9 +74,6 @@ ManagedSession::~ManagedSession() // Don't let any callbacks use this CoreSession anymore switch_channel_set_private(channel, "CoreSession", NULL); } - // Free delegates - hangupDelegateHandle.Free(); - dtmfDelegateHandle.Free(); } bool ManagedSession::begin_allow_threads() @@ -91,22 +88,23 @@ bool ManagedSession::end_allow_threads() void ManagedSession::check_hangup_hook() { - if (!hangupDelegateHandle.IsAllocated) { + if (!hangupDelegate) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangupDelegateHandle didn't get an object."); return; } - ((HangupDelegate^)hangupDelegateHandle.Target)(); + hangupDelegate(); } switch_status_t ManagedSession::run_dtmf_callback(void *input, switch_input_type_t itype) { - if (!dtmfDelegateHandle.IsAllocated) { + if (!dtmfDelegate) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmfDelegateHandle didn't get an object."); return SWITCH_STATUS_FALSE;; } - char *result = ((InputDelegate^)dtmfDelegateHandle.Target)(input, itype); + char *result = dtmfDelegate(input, itype); switch_status_t status = process_callback_result(result); + Marshal::FreeHGlobal(IntPtr(result)); // I think this is right return status; } diff --git a/src/mod/languages/mod_managed/freeswitch_managed.h b/src/mod/languages/mod_managed/freeswitch_managed.h index 97b6d02fde..b5f64c8d5f 100644 --- a/src/mod/languages/mod_managed/freeswitch_managed.h +++ b/src/mod/languages/mod_managed/freeswitch_managed.h @@ -99,8 +99,8 @@ using namespace System; using namespace System::Reflection; using namespace System::Runtime::InteropServices; -delegate void HangupDelegate(void); -delegate char* InputDelegate(void* input, switch_input_type_t type); +typedef void (*hangupFunction)(void); +typedef char* (*inputFunction)(void*, switch_input_type_t); public ref class FreeSwitchManaged { @@ -130,8 +130,9 @@ public: virtual switch_status_t run_dtmf_callback(void *input, switch_input_type_t itype); #ifdef _MANAGED - GCHandle dtmfDelegateHandle; // GCHandle to the input delegate - GCHandle hangupDelegateHandle; // GCHandle to the hangup delegate + // P/Invoke function pointer to delegates + inputFunction dtmfDelegate; + hangupFunction hangupDelegate; #else guint32 dtmfDelegateHandle; // GCHandle to the input delegate guint32 hangupDelegateHandle; // GCHandle to the hangup delegate diff --git a/src/mod/languages/mod_managed/managed/ManagedSession.cs b/src/mod/languages/mod_managed/managed/ManagedSession.cs index e381283b59..5561673aef 100644 --- a/src/mod/languages/mod_managed/managed/ManagedSession.cs +++ b/src/mod/languages/mod_managed/managed/ManagedSession.cs @@ -47,8 +47,16 @@ namespace FreeSWITCH.Native /// Initializes the native ManagedSession. Must be called after Originate. public void Initialize() { + // P/Invoke generated function pointers stick around until the delegate is collected + // By sticking the delegates in fields, their lifetime won't be less than the session + // So we don't need to worry about GCHandles and all that.... + // Info here: http://blogs.msdn.com/cbrumme/archive/2003/05/06/51385.aspx + this._inputCallbackRef = inputCallback; + this._hangupCallback = hangupCallback; InitManagedSession(ManagedSession.getCPtr(this).Handle, inputCallback, hangupCallback); } + DtmfCallback _inputCallbackRef; + Action _hangupCallback; /// Function to execute when this session hangs up. public Action HangupFunction { get; set; } diff --git a/src/mod/languages/mod_managed/mod_managed.cpp b/src/mod/languages/mod_managed/mod_managed.cpp index cca9fe7248..1f19e4a105 100644 --- a/src/mod/languages/mod_managed/mod_managed.cpp +++ b/src/mod/languages/mod_managed/mod_managed.cpp @@ -452,8 +452,7 @@ struct dotnet_conf_t { // Sets up delegates (and anything else needed) on the ManagedSession object // Called from ManagedSession.Initialize Managed -> this is Unmanaged code so all pointers are marshalled and prevented from GC // Exported method. - -SWITCH_MOD_DECLARE(void) InitManagedSession(ManagedSession *session, void *dtmfDelegate, void *hangupDelegate) +SWITCH_MOD_DECLARE(void) InitManagedSession(ManagedSession *session, inputFunction dtmfDelegate, hangupFunction hangupDelegate) { switch_assert(session); if (!session) { @@ -461,8 +460,8 @@ SWITCH_MOD_DECLARE(void) InitManagedSession(ManagedSession *session, void *dtmfD } session->setDTMFCallback(NULL, ""); session->setHangupHook(NULL); - session->dtmfDelegateHandle = GCHandle::Alloc(Marshal::GetDelegateForFunctionPointer(IntPtr(dtmfDelegate), InputDelegate::typeid)); - session->hangupDelegateHandle = GCHandle::Alloc(Marshal::GetDelegateForFunctionPointer(IntPtr(hangupDelegate), HangupDelegate::typeid)); + session->dtmfDelegate = dtmfDelegate; + session->hangupDelegate = hangupDelegate; } switch_status_t loadModDotnetManaged()