]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
No more dynamic invoke for run/execute[bg]
authorMichael Giagnocavo <mgg@giagnocavo.net>
Sat, 4 Oct 2008 21:29:32 +0000 (21:29 +0000)
committerMichael Giagnocavo <mgg@giagnocavo.net>
Sat, 4 Oct 2008 21:29:32 +0000 (21:29 +0000)
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9841 d0543943-73ff-0310-b7d9-9358b9ac24b2

src/mod/languages/mod_managed/freeswitch_managed.h
src/mod/languages/mod_managed/managed/Loader.cs
src/mod/languages/mod_managed/mod_managed.cpp

index b1be25e3148e6db44e84e3f3473ea651e25e0f40..2bbd0b80b652388a4ff0966ae15d922c0d25966a 100644 (file)
@@ -41,6 +41,7 @@ SWITCH_BEGIN_EXTERN_C
 typedef void (*hangupFunction)(void);\r
 typedef char* (*inputFunction)(void*, switch_input_type_t);\r
 \r
+\r
 #ifndef _MANAGED\r
 #include <glib.h>\r
 #include <mono/jit/jit.h>\r
@@ -60,9 +61,6 @@ struct mod_managed_globals {
 \r
        MonoMethod *loadMethod;\r
        MonoMethod *unloadMethod;\r
-       MonoMethod *runMethod;\r
-       MonoMethod *executeMethod;\r
-       MonoMethod *executeBackgroundMethod;\r
 #endif\r
 };\r
 typedef struct mod_managed_globals mod_managed_globals;\r
@@ -124,9 +122,6 @@ public:
        static Assembly^ mod_dotnet_managed;\r
        static MethodInfo^ loadMethod;\r
        static MethodInfo^ unloadMethod;\r
-       static MethodInfo^ runMethod;\r
-       static MethodInfo^ executeMethod;\r
-       static MethodInfo^ executeBackgroundMethod;\r
 };\r
 \r
 #endif\r
index c49ad78954b01de943f327ac11e208ee1fa13ee6..00b5e54f97d01879a612884127eba09042951dca 100644 (file)
@@ -36,6 +36,7 @@ using System.Text;
 using System.IO;\r
 using System.Linq;\r
 using System.Reflection;\r
+using System.Runtime.InteropServices;\r
 \r
 namespace FreeSWITCH\r
 {\r
@@ -65,6 +66,8 @@ namespace FreeSWITCH
                 return File.Exists(path) ? Assembly.LoadFile(path) : null;\r
             };\r
 \r
+            InitManagedDelegates(_run, _execute, _executeBackground);\r
+\r
             // This is a simple one-time loader to get things in memory\r
             // Some day we should allow reloading of modules or something\r
             loadAssemblies(managedDir)\r
@@ -77,6 +80,16 @@ namespace FreeSWITCH
             return true;\r
         }\r
 \r
+        delegate bool ExecuteDelegate(string cmd, IntPtr streamH, IntPtr eventH);\r
+        delegate bool ExecuteBackgroundDelegate(string cmd);\r
+        delegate bool RunDelegate(string cmd, IntPtr session);\r
+        static readonly ExecuteDelegate _execute = Execute;\r
+        static readonly ExecuteBackgroundDelegate _executeBackground = ExecuteBackground;\r
+        static readonly RunDelegate _run = Run;\r
+        //SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground) \r
+        [DllImport("mod_managed")]\r
+        static extern void InitManagedDelegates(RunDelegate run, ExecuteDelegate execute, ExecuteBackgroundDelegate executeBackground);\r
+\r
         // Be rather lenient in finding the Load and Unload methods\r
         static readonly BindingFlags methodBindingFlags =\r
             BindingFlags.Static | // Required\r
@@ -181,25 +194,29 @@ namespace FreeSWITCH
 \r
         public static bool ExecuteBackground(string command)\r
         {\r
-            var parsed = parseCommand(command);\r
-            if (parsed == null) return false;\r
-            var fullName = parsed[0];\r
-            var args = parsed[1];\r
+            try {\r
+                var parsed = parseCommand(command);\r
+                if (parsed == null) return false;\r
+                var fullName = parsed[0];\r
+                var args = parsed[1];\r
 \r
-            var fType = getFunctionType<ApiFunction>(fullName);\r
-            if (fType == null) return false;\r
+                var fType = getFunctionType<ApiFunction>(fullName);\r
+                if (fType == null) return false;\r
 \r
-            new System.Threading.Thread(() => {\r
-                try {\r
-                    var f = (ApiFunction)Activator.CreateInstance(fType);\r
-                    f.ExecuteBackground(args);\r
-                    Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName);\r
-                }\r
-                catch (Exception ex) {\r
-                    logException("ExecuteBackground", fullName, ex);\r
-                }\r
-            }).Start();\r
-            return true;\r
+                new System.Threading.Thread(() => {\r
+                    try {\r
+                        var f = (ApiFunction)Activator.CreateInstance(fType);\r
+                        f.ExecuteBackground(args);\r
+                        Log.WriteLine(LogLevel.Debug, "ExecuteBackground in {0} completed.", fullName);\r
+                    } catch (Exception ex) {\r
+                        logException("ExecuteBackground", fullName, ex);\r
+                    }\r
+                }).Start();\r
+                return true;\r
+            } catch (Exception ex) {\r
+                Log.WriteLine(LogLevel.Error, "Exception in ExecuteBackground({0}): {1}", command, ex.ToString());\r
+                return false;\r
+            }\r
         }\r
 \r
         public static bool Execute(string command, IntPtr streamHandle, IntPtr eventHandle)\r
index 1882c196cef89e46aa315342266bd6c421dea6e4..7233db8c2d19c2f87ebef12611b5de81161a46b6 100644 (file)
@@ -63,6 +63,21 @@ SWITCH_STANDARD_APP(managed_app_function);   /* Run */
 \r
 mod_managed_globals globals = { 0 };\r
 \r
+// Global delegates to call managed functions\r
+typedef int (*runFunction)(const char *data, void *sessionPtr);\r
+typedef int (*executeFunction)(const char *cmd, void *stream, void *Event);\r
+typedef int (*executeBackgroundFunction)(const char* cmd);\r
+static runFunction runDelegate;\r
+static executeFunction executeDelegate;\r
+static executeBackgroundFunction executeBackgroundDelegate;\r
+\r
+SWITCH_MOD_DECLARE(void) InitManagedDelegates(runFunction run, executeFunction execute, executeBackgroundFunction executeBackground) \r
+{\r
+       runDelegate = run;\r
+       executeDelegate = execute;\r
+       executeBackgroundDelegate = executeBackground;\r
+}\r
+\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
@@ -222,6 +237,7 @@ MonoMethod * getMethod(const char *name, MonoClass * klass)
        return method;\r
 }\r
 \r
+\r
 switch_status_t findLoader() \r
 {\r
        /* Find loader class and methods */ \r
@@ -241,18 +257,6 @@ switch_status_t findLoader()
                return SWITCH_STATUS_FALSE;\r
        }\r
 \r
-       if (!(globals.runMethod = getMethod("FreeSWITCH.Loader:Run(string,intptr)", loaderClass))) {\r
-               return SWITCH_STATUS_FALSE;\r
-       }\r
-\r
-       if (!(globals.executeMethod = getMethod("FreeSWITCH.Loader:Execute(string,intptr,intptr)", loaderClass))) {\r
-               return SWITCH_STATUS_FALSE;\r
-       }\r
-\r
-       if (!(globals.executeBackgroundMethod = getMethod("FreeSWITCH.Loader:ExecuteBackground(string)", loaderClass))) {\r
-               return SWITCH_STATUS_FALSE;\r
-       }\r
-\r
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Found all loader functions.\n");\r
        return SWITCH_STATUS_SUCCESS;\r
 }\r
@@ -288,9 +292,6 @@ switch_status_t findLoader()
        try {\r
                FreeSwitchManaged::loadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Load");\r
                FreeSwitchManaged::unloadMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Unload");\r
-               FreeSwitchManaged::runMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Run");\r
-               FreeSwitchManaged::executeMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("Execute");\r
-               FreeSwitchManaged::executeBackgroundMethod = FreeSwitchManaged::mod_dotnet_managed->GetType("FreeSWITCH.Loader")->GetMethod("ExecuteBackground");\r
        } catch(Exception^ ex) {\r
                IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not load FreeSWITCH.Loader class: %s\n", static_cast<const char*>(msg.ToPointer()));\r
@@ -372,40 +373,12 @@ SWITCH_STANDARD_API(managedrun_api_function)
                stream->write_function(stream, "-ERR no args specified!\n");    \r
                return SWITCH_STATUS_SUCCESS;\r
        }\r
-#ifdef _MANAGED\r
-       Object ^objResult;\r
-       try {\r
-               objResult = FreeSwitchManaged::executeBackgroundMethod->Invoke(nullptr, gcnew array<Object^> { gcnew String(cmd) } );\r
-               success = *reinterpret_cast<bool^>(objResult);\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Load completed successfully.\n");\r
-       } catch(Exception^ ex)  {\r
-               IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
-               stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception: %s\n", static_cast<const char*>(msg.ToPointer()));\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Load did not return true: %s\n", static_cast<const char*>(msg.ToPointer()));\r
-               Marshal::FreeHGlobal(msg);\r
-               return SWITCH_STATUS_FALSE;\r
-       }\r
-#else\r
-       mono_thread_attach(globals.domain);\r
-       void *args[1];\r
-\r
-       args[0] = mono_string_new(globals.domain, cmd);\r
-       MonoObject * exception = NULL;\r
-       MonoObject * objResult = mono_runtime_invoke(globals.executeBackgroundMethod, NULL, args, &exception);\r
-       success = *(int *) mono_object_unbox(objResult);\r
-\r
-       if (exception) {\r
-               stream->write_function(stream, "-ERR FreeSWITCH.Loader.ExecuteBackground threw an exception.\n");\r
-               mono_print_unhandled_exception(exception);\r
-               return SWITCH_STATUS_SUCCESS;\r
-       }\r
-#endif\r
+       success = executeBackgroundDelegate(cmd);\r
        if (success) {\r
                stream->write_function(stream, "+OK\n");\r
        } else {        \r
-               stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module?).\n");\r
+               stream->write_function(stream, "-ERR ExecuteBackground returned false (unknown module or exception?).\n");\r
        }\r
-\r
        return SWITCH_STATUS_SUCCESS;\r
 }\r
 \r
@@ -417,37 +390,9 @@ SWITCH_STANDARD_API(managed_api_function)
                stream->write_function(stream, "-ERR no args specified!\n");    \r
                return SWITCH_STATUS_SUCCESS;\r
        }\r
-#ifdef _MANAGED\r
-       Object ^objResult;\r
-       try {\r
-               objResult = FreeSwitchManaged::executeMethod->Invoke(nullptr, gcnew array<Object^>{gcnew String(cmd),gcnew IntPtr(stream), gcnew IntPtr(stream->param_event)});\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Execute completed successfully.\n");\r
-               success = *reinterpret_cast<bool^>(objResult);\r
-       } catch(Exception ^ex)  {\r
-               IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute cli %s: %s\n", cmd, static_cast<const char*>(msg.ToPointer()));\r
-               Marshal::FreeHGlobal(msg);\r
-               return SWITCH_STATUS_FALSE;\r
-       }\r
-#else\r
-       mono_thread_attach(globals.domain);\r
-       void *args[3];\r
-\r
-       args[0] = mono_string_new(globals.domain, cmd);\r
-       args[1] = &stream;                      // Address of the arguments\r
-       args[2] = &(stream->param_event);\r
-\r
-       MonoObject * exception = NULL;\r
-       MonoObject * objResult = mono_runtime_invoke(globals.executeMethod, NULL, args, &exception);\r
-       success = *(int *) mono_object_unbox(objResult);\r
-\r
-       if (exception) {\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute mono %s.\n", cmd);\r
-               mono_print_unhandled_exception(exception);\r
-       }\r
-#endif\r
+       success = executeDelegate(cmd, stream, stream->param_event);\r
        if (!success) {\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module?).\n", cmd);\r
+               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Execute failed for %s (unknown module or exception).\n", cmd); \r
        }\r
        return SWITCH_STATUS_SUCCESS;\r
 }\r
@@ -458,42 +403,16 @@ SWITCH_STANDARD_APP(managed_app_function)
        int success;\r
        if (switch_strlen_zero(data)) {\r
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No args specified!\n");\r
-       }\r
-#ifdef _MANAGED\r
-       Object ^objResult;\r
-       try {\r
-               objResult = FreeSwitchManaged::runMethod->Invoke(nullptr, gcnew array<Object^>{gcnew String(data),gcnew IntPtr(session)});\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "RunMethod completed successfully.\n");\r
-               success = *reinterpret_cast<bool^>(objResult);\r
-       }\r
-       catch(Exception ^ex)    {\r
-               IntPtr msg = Marshal::StringToHGlobalAnsi(ex->ToString());\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s %s.\n", data, static_cast<const char*>(msg.ToPointer()));\r
-               Marshal::FreeHGlobal(msg);\r
                return;\r
        }\r
-#else\r
-       mono_thread_attach(globals.domain);\r
-       void *args[2];\r
-\r
-       args[0] = mono_string_new(globals.domain, data);\r
-       args[1] = &session;\r
-\r
-       MonoObject * exception = NULL;\r
-       MonoObject * objResult = mono_runtime_invoke(globals.runMethod, NULL, args, &exception);\r
-       success = *(int *) mono_object_unbox(objResult);\r
-\r
-       if (exception) {\r
-               switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Exception trying to execute application mono %s.\n", data);\r
-               mono_print_unhandled_exception(exception);\r
-       }\r
-#endif\r
+       success = runDelegate(data, session);\r
        if (!success) {\r
                switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Application run failed for %s (unknown module?).\n", data);\r
        }\r
 }\r
 \r
 \r
+\r
 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_managed_shutdown) \r
 {\r
 #ifdef _MANAGED\r