From 19811e4f08b3bd8290b3692d5bd2672bad160dde Mon Sep 17 00:00:00 2001 From: Michael Jerris Date: Tue, 16 Sep 2008 23:54:23 +0000 Subject: [PATCH] (MODLANG-83) mod_mono Linux build & embedding git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9576 d0543943-73ff-0310-b7d9-9358b9ac24b2 --- src/mod/languages/mod_mono/Makefile | 16 ++++++ src/mod/languages/mod_mono/freeswitch.i | 1 + src/mod/languages/mod_mono/freeswitch_mono.h | 3 +- src/mod/languages/mod_mono/mod_mono.cpp | 57 ++++++++++++++------ src/mod/languages/mod_mono/runswig.sh | 5 ++ src/mod/languages/mod_mono/switch_platform.i | 16 +++++- src/mod/languages/mod_mono_managed/Loader.cs | 30 +++++------ src/mod/languages/mod_mono_managed/Makefile | 13 +++++ 8 files changed, 109 insertions(+), 32 deletions(-) create mode 100644 src/mod/languages/mod_mono/Makefile create mode 100644 src/mod/languages/mod_mono/runswig.sh create mode 100644 src/mod/languages/mod_mono_managed/Makefile diff --git a/src/mod/languages/mod_mono/Makefile b/src/mod/languages/mod_mono/Makefile new file mode 100644 index 0000000000..0bae30a26b --- /dev/null +++ b/src/mod/languages/mod_mono/Makefile @@ -0,0 +1,16 @@ +#MOD_CFLAGS=`pkg-config --cflags --libs mono` +MOD_CFLAGS=-D_REENTRANT -pthread -I/opt/mono-1.9/lib/pkgconfig/../../include/mono-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -lmono +#LDFLAGS=`pkg-config --libs mono` +BASE=../../../.. +VERBOSE=1 +include $(BASE)/build/modmake.rules +LOCAL_OBJS=freeswitch_mono.o freeswitch_wrap.o +local_depend: $(LOCAL_OBJS) + +freeswitch_mono.o: freeswitch_mono.h freeswitch_mono.cpp + +freeswitch_wrap.o: freeswitch_wrap.cpp + +freeswitch_wrap.cpp: freeswitch_wrap.cxx + cp freeswitch_wrap.cxx freeswitch_wrap.cpp + diff --git a/src/mod/languages/mod_mono/freeswitch.i b/src/mod/languages/mod_mono/freeswitch.i index 1d5b917963..5cb7931a9d 100644 --- a/src/mod/languages/mod_mono/freeswitch.i +++ b/src/mod/languages/mod_mono/freeswitch.i @@ -107,6 +107,7 @@ %ignore switch_core_session_get_event_hooks; %ignore switch_inet_pton; %ignore switch_xml_idx; +%ignore switch_xml_pi; // Real header includes now %import switch_platform.i // This will give us all the macros we need to compile the other stuff diff --git a/src/mod/languages/mod_mono/freeswitch_mono.h b/src/mod/languages/mod_mono/freeswitch_mono.h index 3bc17bc7e1..341ff25a2d 100644 --- a/src/mod/languages/mod_mono/freeswitch_mono.h +++ b/src/mod/languages/mod_mono/freeswitch_mono.h @@ -44,6 +44,7 @@ struct mod_mono_globals { MonoDomain *domain; MonoAssembly *mod_mono_asm; switch_memory_pool_t *pool; + switch_bool_t embedded; MonoMethod *loadMethod; MonoMethod *unloadMethod; @@ -76,4 +77,4 @@ public: guint32 hangupDelegateHandle; // GCHandle to the hangup delegate }; -#endif \ No newline at end of file +#endif diff --git a/src/mod/languages/mod_mono/mod_mono.cpp b/src/mod/languages/mod_mono/mod_mono.cpp index e9ed68abc9..f1c9df101f 100644 --- a/src/mod/languages/mod_mono/mod_mono.cpp +++ b/src/mod/languages/mod_mono/mod_mono.cpp @@ -47,12 +47,18 @@ SWITCH_BEGIN_EXTERN_C #ifdef WIN32 #include #define EXPORT __declspec(dllexport) -#elif +#else #define EXPORT #endif #define MOD_MONO_MANAGED_DLL "mod_mono_managed.dll" - + +#define MOD_MONO_MANAGED_ASM_NAME "mod_mono_managed" +#define MOD_MONO_MANAGED_ASM_V1 1 +#define MOD_MONO_MANAGED_ASM_V2 0 +#define MOD_MONO_MANAGED_ASM_V3 0 +#define MOD_MONO_MANAGED_ASM_V4 0 + mod_mono_globals globals = { 0 }; @@ -120,7 +126,7 @@ switch_status_t setMonoDirs() return SWITCH_STATUS_SUCCESS; } -#elif +#else // On other platforms, it should just work if it hasn't been relocated mono_set_dirs(NULL, NULL); return SWITCH_STATUS_SUCCESS; @@ -137,20 +143,41 @@ switch_status_t loadModMonoManaged() switch_snprintf(filename, 256, "%s%s%s", SWITCH_GLOBAL_dirs.mod_dir, SWITCH_PATH_SEPARATOR, MOD_MONO_MANAGED_DLL); globals.domain = mono_jit_init(filename); - if (!globals.domain) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_jit_init failed.\n"); - return SWITCH_STATUS_FALSE; + /* Already got a Mono domain? */ + if ((globals.domain = mono_get_root_domain())) { + mono_thread_attach(globals.domain); + globals.embedded = SWITCH_TRUE; + } else { + if (!(globals.domain = mono_jit_init(filename))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_jit_init failed.\n"); + return SWITCH_STATUS_FALSE; + } } - /* Open the assembly */ - globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename); + /* Already loaded? */ + MonoAssemblyName name; + name.name = MOD_MONO_MANAGED_ASM_NAME; + name.major = MOD_MONO_MANAGED_ASM_V1; + name.minor = MOD_MONO_MANAGED_ASM_V2; + name.revision = MOD_MONO_MANAGED_ASM_V3; + name.build = MOD_MONO_MANAGED_ASM_V4; + name.culture = ""; + name.hash_value = ""; - if (!globals.mod_mono_asm) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_domain_assembly_open failed.\n"); - return SWITCH_STATUS_FALSE; + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_assembly_loaded"); + + if (!(globals.mod_mono_asm = mono_assembly_loaded(&name))) { + /* Open the assembly */ + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Calling mono_domain_assembly_open"); + globals.mod_mono_asm = mono_domain_assembly_open(globals.domain, filename); + if (!globals.mod_mono_asm) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "mono_domain_assembly_open failed.\n"); + return SWITCH_STATUS_FALSE; + } } return SWITCH_STATUS_SUCCESS; + } MonoMethod * getMethod(const char *name, MonoClass * klass) @@ -226,7 +253,7 @@ SWITCH_MODULE_LOAD_FUNCTION(mod_mono_load) /* Not sure if this is necesary on the loading thread */ mono_thread_attach(globals.domain); - mono_add_internal_call("FreeSWITCH.Native.MonoSession::InitMonoSession", InitMonoSession); + mono_add_internal_call("FreeSWITCH.Native.MonoSession::InitMonoSession", (void *)InitMonoSession); /* Run loader */ MonoObject * objResult; @@ -360,9 +387,9 @@ SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_mono_shutdown) mono_print_unhandled_exception(ex); } - mono_runtime_set_shutting_down(); - mono_runtime_cleanup(globals.domain); - mono_runtime_quit(); + if (!globals.embedded) { + mono_jit_cleanup(globals.domain); + } return SWITCH_STATUS_SUCCESS; } diff --git a/src/mod/languages/mod_mono/runswig.sh b/src/mod/languages/mod_mono/runswig.sh new file mode 100644 index 0000000000..86e85a057e --- /dev/null +++ b/src/mod/languages/mod_mono/runswig.sh @@ -0,0 +1,5 @@ +#!/bin/bash +swig -I../../../include -v -O -c++ -csharp -namespace FreeSWITCH.Native -dllimport mod_mono freeswitch.i +rm -f ../mod_mono_managed/swig.cs +cat *.cs > ../mod_mono_managed/swig.cs +rm -f *.cs diff --git a/src/mod/languages/mod_mono/switch_platform.i b/src/mod/languages/mod_mono/switch_platform.i index 81e062fae6..262acc6c44 100644 --- a/src/mod/languages/mod_mono/switch_platform.i +++ b/src/mod/languages/mod_mono/switch_platform.i @@ -14,6 +14,20 @@ typedef unsigned long in_addr_t; // we define char as byte. // TODO: Possible? It'd be nice to do the whole char*->IntPtr->Marshal/Free thing here instead of swigStringFix +%typemap(imtype, out="string") char ** "ref string" +%typemap(cstype, out="string") char ** "ref string" +%typemap(csin) char ** "ref $csinput" +%typemap(csvarin) char ** +%{ + set { $imcall; } +%} +%typemap(csvarout) char ** +%{ + get { + return $imcall; + } +%} + #define SWITCH_DECLARE(type) type #define SWITCH_DECLARE_NONSTD(type) type #define SWITCH_MOD_DECLARE(type) type @@ -42,4 +56,4 @@ typedef unsigned long in_addr_t; #define _Out_cap_(x) #define _Out_z_cap_(x) #define _Out_ptrdiff_cap_(x) -#define _Out_opt_ptrdiff_cap_(x) \ No newline at end of file +#define _Out_opt_ptrdiff_cap_(x) diff --git a/src/mod/languages/mod_mono_managed/Loader.cs b/src/mod/languages/mod_mono_managed/Loader.cs index a8d254ffe6..ade3509a94 100644 --- a/src/mod/languages/mod_mono_managed/Loader.cs +++ b/src/mod/languages/mod_mono_managed/Loader.cs @@ -100,22 +100,22 @@ namespace FreeSWITCH } } - static List loadAssemblies(string managedDir) + static Assembly[] loadAssemblies(string managedDir) { - return Directory.GetFiles(managedDir, "*.dll", SearchOption.AllDirectories) - .Select(f => Path.Combine(managedDir, f)) - .Select(f => { - try { - return System.Reflection.Assembly.LoadFile(f); - } - catch (Exception ex) { - Log.WriteLine(LogLevel.Notice, "Assembly.LoadFile failed; skipping {0} ({1})", f, ex.Message); - return null; - } - }) - .Where(a => a != null) - .Concat(new[] { System.Reflection.Assembly.GetExecutingAssembly() }) // Add in our own to load Demo or built-in things if added - .ToList(); + // load the modules in the mod/mono directory + Log.WriteLine(LogLevel.Notice, "loadAssemblies: {0}", managedDir); + foreach (string s in Directory.GetFiles(managedDir, "*.dll", SearchOption.AllDirectories)) + { + string f = Path.Combine(managedDir, s); + try { + System.Reflection.Assembly.LoadFile(f); + } + catch (Exception ex) { + Log.WriteLine(LogLevel.Notice, "Assembly.LoadFile failed; skipping {0} ({1})", f, ex.Message); + } + } + + return AppDomain.CurrentDomain.GetAssemblies(); // Includes anything else already loaded } public static void Unload() diff --git a/src/mod/languages/mod_mono_managed/Makefile b/src/mod/languages/mod_mono_managed/Makefile new file mode 100644 index 0000000000..0fde8fee0f --- /dev/null +++ b/src/mod/languages/mod_mono_managed/Makefile @@ -0,0 +1,13 @@ +all: Debug Debug/mod_mono_managed.dll + +clean: + rm -fr Debug + +Debug: + mkdir Debug + +Debug/mod_mono_managed.dll: Loader.cs MonoSession.cs ApiFunction.cs AppFunction.cs Extensions.cs Log.cs Demo.cs swig.cs + gmcs -target:library -out:Debug/mod_mono_managed.dll -d:DEBUG Loader.cs MonoSession.cs ApiFunction.cs AppFunction.cs Extensions.cs Log.cs Demo.cs swig.cs + +install: Debug/mod_mono_managed.dll + install Debug/mod_mono_managed.dll /usr/local/freeswitch/mod