// Don't let any callbacks use this CoreSession anymore\r
switch_channel_set_private(channel, "CoreSession", NULL);\r
}\r
- // Free delegates\r
- hangupDelegateHandle.Free();\r
- dtmfDelegateHandle.Free();\r
}\r
\r
bool ManagedSession::begin_allow_threads() \r
\r
void ManagedSession::check_hangup_hook() \r
{\r
- if (!hangupDelegateHandle.IsAllocated) {\r
+ if (!hangupDelegate) {\r
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "hangupDelegateHandle didn't get an object.");\r
return;\r
}\r
- ((HangupDelegate^)hangupDelegateHandle.Target)();\r
+ hangupDelegate();\r
}\r
\r
switch_status_t ManagedSession::run_dtmf_callback(void *input, switch_input_type_t itype) \r
{\r
- if (!dtmfDelegateHandle.IsAllocated) {\r
+ if (!dtmfDelegate) {\r
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "dtmfDelegateHandle didn't get an object.");\r
return SWITCH_STATUS_FALSE;;\r
}\r
- char *result = ((InputDelegate^)dtmfDelegateHandle.Target)(input, itype);\r
+ char *result = dtmfDelegate(input, itype);\r
\r
switch_status_t status = process_callback_result(result);\r
+ Marshal::FreeHGlobal(IntPtr(result)); // I think this is right\r
return status;\r
}\r
\r
using namespace System::Reflection;\r
using namespace System::Runtime::InteropServices;\r
\r
-delegate void HangupDelegate(void);\r
-delegate char* InputDelegate(void* input, switch_input_type_t type);\r
+typedef void (*hangupFunction)(void);\r
+typedef char* (*inputFunction)(void*, switch_input_type_t);\r
\r
public ref class FreeSwitchManaged\r
{\r
virtual switch_status_t run_dtmf_callback(void *input, switch_input_type_t itype);\r
\r
#ifdef _MANAGED\r
- GCHandle dtmfDelegateHandle; // GCHandle to the input delegate \r
- GCHandle hangupDelegateHandle; // GCHandle to the hangup delegate\r
+ // P/Invoke function pointer to delegates\r
+ inputFunction dtmfDelegate; \r
+ hangupFunction hangupDelegate; \r
#else\r
guint32 dtmfDelegateHandle; // GCHandle to the input delegate \r
guint32 hangupDelegateHandle; // GCHandle to the hangup delegate\r
/// <summary>Initializes the native ManagedSession. Must be called after Originate.</summary>\r
public void Initialize()\r
{\r
+ // P/Invoke generated function pointers stick around until the delegate is collected\r
+ // By sticking the delegates in fields, their lifetime won't be less than the session\r
+ // So we don't need to worry about GCHandles and all that....\r
+ // Info here: http://blogs.msdn.com/cbrumme/archive/2003/05/06/51385.aspx\r
+ this._inputCallbackRef = inputCallback;\r
+ this._hangupCallback = hangupCallback;\r
InitManagedSession(ManagedSession.getCPtr(this).Handle, inputCallback, hangupCallback);\r
}\r
+ DtmfCallback _inputCallbackRef;\r
+ Action _hangupCallback;\r
\r
/// <summary>Function to execute when this session hangs up.</summary>\r
public Action HangupFunction { get; set; }\r
// Sets up delegates (and anything else needed) on the ManagedSession object\r
// Called from ManagedSession.Initialize Managed -> this is Unmanaged code so all pointers are marshalled and prevented from GC\r
// Exported method.\r
-\r
-SWITCH_MOD_DECLARE(void) InitManagedSession(ManagedSession *session, void *dtmfDelegate, void *hangupDelegate) \r
+SWITCH_MOD_DECLARE(void) InitManagedSession(ManagedSession *session, inputFunction dtmfDelegate, hangupFunction hangupDelegate) \r
{\r
switch_assert(session);\r
if (!session) {\r
}\r
session->setDTMFCallback(NULL, "");\r
session->setHangupHook(NULL);\r
- session->dtmfDelegateHandle = GCHandle::Alloc(Marshal::GetDelegateForFunctionPointer(IntPtr(dtmfDelegate), InputDelegate::typeid));\r
- session->hangupDelegateHandle = GCHandle::Alloc(Marshal::GetDelegateForFunctionPointer(IntPtr(hangupDelegate), HangupDelegate::typeid));\r
+ session->dtmfDelegate = dtmfDelegate;\r
+ session->hangupDelegate = hangupDelegate;\r
}\r
\r
switch_status_t loadModDotnetManaged() \r