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()