From bb19814837e99729321b3ff7305f7ef0ce80354e Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Fri, 27 Jan 2006 22:53:18 +0000 Subject: Completely rewrote the PD side of clr, using class loader hook and much more efficient access svn path=/trunk/externals/clr/; revision=4508 --- PureData.dll | Bin 20480 -> 5120 bytes clr.c | 795 ---------------------------------------- clr.cpp | 1150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test-clr.pd | 65 +--- 4 files changed, 1162 insertions(+), 848 deletions(-) delete mode 100755 clr.c create mode 100755 clr.cpp diff --git a/PureData.dll b/PureData.dll index 82826a6..45bf586 100755 Binary files a/PureData.dll and b/PureData.dll differ diff --git a/clr.c b/clr.c deleted file mode 100755 index 9356402..0000000 --- a/clr.c +++ /dev/null @@ -1,795 +0,0 @@ -/* -just a dummy clr patch - -*/ - -#include "m_pd.h" - -#include -#include -#include - -// mono -#include -#include -#include -#include -#include -#include -#include - -#define MAX_SELECTORS 256 -#define MAX_OUTLETS 32 - -void *clr_new(t_symbol *s, int argc, t_atom *argv); - -// list of mono methods -typedef struct selectorList selectorList; -typedef struct selectorList -{ - char *sel; // the selector - MonoMethod *func; // the function - int type; -// selectorList *next; // next element of the list -}; - -// list of outlets -typedef struct outletList outletList; -typedef struct outletList -{ - t_outlet *outlet_pointer; -// outletList *next; // next element of the list -}; - -// simplyfied atom -typedef struct atom_simple atom_simple; -typedef enum -{ - A_S_NULL=0, - A_S_FLOAT=1, - A_S_SYMBOL=2, -} t_atomtype_simple; - -typedef struct atom_simple -{ - //t_atomtype_simple a_type; - int a_type; - float float_value; - MonoString *string_value; - -}; - -static t_class *clr_class; - -typedef struct _clr -{ - t_object x_obj; // myself - t_outlet *l_out; - t_symbol *assemblyname; - t_symbol *filename; - int loaded; - // mono stuff - MonoDomain *domain; - MonoAssembly *assembly, *assemblyPureData; - MonoObject *obj; - MonoImage *image, *imagePureData; - MonoMethod *method, *setUp, *manageBang, *manageSymbol, *manageFloat, *manageList; - MonoClass *klass; - int n; - - // TODO: dynamic memory allocation - selectorList selectors[MAX_SELECTORS]; - outletList outlets[MAX_OUTLETS]; - -} t_clr; - - -// mono functions - -static void mono_clean(t_clr *x) -{ - // clean up stuff - //mono_jit_cleanup (x->domain); - //mono_domain_free(x->domain); -} - -void registerMonoMethod(void *x, MonoString *selectorString, MonoString *methodString, int type); -void createInlet(void *x1, MonoString *selectorString, int type); -void createOutlet(void *x1, int type); -void out2outlet(void *x1, int outlet, int atoms_length, MonoArray *array); -void post2pd(MonoString *mesString); -void error2pd(MonoString *mesString); - -static void mono_initialize() -{ - mono_jit_init ("PureData"); -} - -// load the variables and init mono -static void mono_load(t_clr *x, int argc, t_atom *argv) -{ -// const char *file="D:\\Davide\\cygwin\\home\\Davide\\externalTest1.dll"; - //const char *file="External.dll"; - - MonoMethod *m = NULL, *ctor = NULL, *fail = NULL, *mvalues; - MonoClassField *classPointer; - gpointer iter; - gpointer *args; - int val; - int i,j; - int params; - t_symbol *strsymbol; - atom_simple *listparams; - - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - - // prepare the selectors list - for (i=0; iselectors[i].sel = 0; - x->selectors[i].func = 0; - } - // and the outlets list - for (i=0; ioutlets[i].outlet_pointer = 0; - } - - //mono_set_dirs (NULL, NULL); - //mono_config_parse (NULL); - - //mono_jit_init (random_name_str); - x->domain = mono_domain_get(); - x->assembly = mono_domain_assembly_open (x->domain, x->filename->s_name); - x->assemblyPureData = mono_domain_assembly_open (x->domain, "PureData.dll"); - - if (!x->assembly) - { - error("clr: file %s not found!", x->filename->s_name); - return; - } - - if (!x->assemblyPureData) - { - error("clr: assembly PureData.dll not found! it is necessary!"); - return; - } - - x->image = mono_assembly_get_image (x->assembly); - - x->imagePureData = mono_assembly_get_image (x->assemblyPureData); - - - x->klass = mono_class_from_name (x->image, "PureData", x->assemblyname->s_name); - if (!x->klass) { - error("Can't find %s in assembly %s\n", x->assemblyname->s_name, mono_image_get_filename (x->image)); - return; - } - x->obj = mono_object_new (x->domain, x->klass); - - //mono_runtime_object_init (x->obj); - - if (argc>2) - params = argc - 2; - else - params = 0; - - /* retrieve all the methods we need */ - iter = NULL; - while ((m = mono_class_get_methods (x->klass, &iter))) { - if (strcmp (mono_method_get_name (m), "test") == 0) { - x->method = m; - } else if (strcmp (mono_method_get_name (m), "SetUp") == 0) { - x->setUp = m; - } else if (strcmp (mono_method_get_name (m), "Fail") == 0) { - fail = m; - } else if (strcmp (mono_method_get_name (m), "Values") == 0) { - mvalues = m; - } else if (strcmp (mono_method_get_name (m), ".ctor") == 0) { - /* Check it's the ctor that takes two args: - * as you see a contrsuctor is a method like any other. - */ - MonoMethodSignature * sig = mono_method_signature (m); - if (mono_signature_get_param_count (sig) == params) { - ctor = m; - } - } - } - // set the pointer - classPointer = 0; - classPointer = mono_class_get_field_from_name (x->klass, "x"); - if (classPointer) - { - mono_field_set_value (x->obj, classPointer, &x); - - } else - { - error("could not find the x field in %s, it is needed!", x->assemblyname->s_name); - return; - } - // call the base functions - if (x->setUp) - { - mono_runtime_invoke (x->setUp, x->obj, NULL, NULL); - post("SetUp() invoked"); - } else - { - error("clr: the provided assembly is not valid! the SetUp function is missing"); - return; - } - // now call the class constructor - if (ctor) - { - args = malloc(sizeof(gpointer)*params); - listparams = malloc(sizeof(atom_simple)*params); - for (j=2; ja_type) - { - case A_FLOAT: - listparams[j-2].a_type = A_S_FLOAT; - listparams[j-2].float_value = (double) atom_getfloat(argv+j); - args[j-2] = &(listparams[j-2].float_value); - break; - case A_SYMBOL: - listparams[j-2].a_type = A_S_SYMBOL; - strsymbol = atom_getsymbol(argv+j); - listparams[j-2].string_value = mono_string_new (x->domain, strsymbol->s_name); - args[j-2] = listparams[j-2].string_value; - break; - } - } - mono_runtime_invoke (ctor, x->obj, args, NULL); - free(listparams); - free(args); - } else - { - error("%s doesn't have a constructor with %i parameters!",x->assemblyname->s_name, params); - } - - // all done without errors - x->loaded = 1; - -} - -/* -// call the method -static void clr_bang(t_clr *x) { - - gpointer args [2]; - int val; - MonoObject *result; - - val = x->n; - args [0] = &val; - - if (x->method) - { - result = mono_runtime_invoke (x->method, x->obj, args, NULL); - val = *(int*)mono_object_unbox (result); - x->n = val; - // outlet_float(x->l_out, (float) x->n); - } - - -} -*/ - -// finds a method from its name -void findMonoMethod( MonoClass *klass, char *function_name, MonoMethod **met) -{ - int trovato; - MonoMethod *m = NULL; - gpointer iter; - iter = NULL; - while (m = mono_class_get_methods (klass, &iter)) - { - if (strcmp (mono_method_get_name (m), function_name) == 0) - { - *met = m; -//printf("%s trovata\n", function_name); - return; - } - } -} - -void clr_free(t_clr *x) -{ - mono_clean(x); -} - -static void clr_bang(t_clr *x) -{ - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - if (x->manageBang) - { - mono_runtime_invoke (x->manageBang, x->obj, NULL, NULL); - } -} - -static void clr_symbol(t_clr *x, t_symbol *sl) -{ - gpointer args [1]; - MonoString *strmono; - strmono = mono_string_new (x->domain, sl->s_name); - args[0] = &strmono; - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - if (x->manageSymbol) - { - mono_runtime_invoke (x->manageSymbol, x->obj, args, NULL); - } -} - -static void clr_float(t_clr *x, float f) -{ - gpointer args [1]; - args [0] = &f; - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - if (x->manageFloat) - { - mono_runtime_invoke (x->manageFloat, x->obj, args, NULL); - } -} - -// here i look for the selector and call the right mono method -void clr_manage_list(t_clr *x, t_symbol *sl, int argc, t_atom *argv) -{ - gpointer args [2]; - int valInt; - float valFloat; - - int i; - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - - // check if a selector is present ! - //printf("clr_manage_list, got symbol = %s\n", sl->s_name); - if (strcmp("list", sl->s_name) == 0) - { - printf("lista senza selector"); - if (x->manageList) - { - gpointer args [1]; - MonoString *stringtmp; - double *floattmp; - t_atomtype_simple *typetmp; - t_symbol *strsymbol; - MonoArray *atoms; - atom_simple *atom_array; - int j; - char strfloat[256], strnull[256]; - sprintf(strfloat, "float"); - sprintf(strnull, "null"); - atom_array = malloc(sizeof(atom_simple)*argc); - MonoClass *c = mono_class_from_name (x->imagePureData, "PureData", "Atom"); - atoms = mono_array_new (x->domain, c, argc); - for (j=0; ja_type) - { - case A_FLOAT: - atom_array[j].a_type = A_S_FLOAT; - atom_array[j].float_value = (double) atom_getfloat(argv+j); - atom_array[j].string_value = mono_string_new (x->domain, strfloat); - break; - case A_SYMBOL: - atom_array[j].a_type = A_S_SYMBOL; - strsymbol = atom_getsymbol(argv+j); - atom_array[j].string_value = mono_string_new (x->domain, strsymbol->s_name); - atom_array[j].float_value = 0; - break; - default: - atom_array[j].a_type = A_S_NULL; - atom_array[j].float_value = 0; - atom_array[j].string_value = mono_string_new (x->domain, strnull); - } - mono_array_set (atoms, atom_simple , j, atom_array[j]); - } - - args[0] = atoms; - mono_runtime_invoke (x->manageList, x->obj, args, NULL); - return; - } else - { - error("you did not specified a function to call for lists without selectors"); - return; - } - } - for (i=0; iselectors[i].sel, sl->s_name) == 0) - { - // I've found the selector! - if (x->selectors[i].func) - { - // ParametersType {None = 0, Float=1, Symbol=2, List=3}; - switch (x->selectors[i].type) - { - case 0: - mono_runtime_invoke (x->selectors[i].func, x->obj, NULL, NULL); - break; - case 1: - { - gpointer args [1]; - float val = atom_getfloat(argv); - args[0] = &val; - mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); - break; - } - case 2: - { - gpointer args [1]; - t_symbol *strsymbol; - MonoString *strmono; - strsymbol = atom_getsymbol(argv); - strmono = mono_string_new (x->domain, strsymbol->s_name); - args[0] = &strmono; - mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); - // memory leak ? - break; - } - case 3: - { - gpointer args [1]; - MonoString *stringtmp; - double *floattmp; - t_atomtype_simple *typetmp; - t_symbol *strsymbol; - MonoArray *atoms; - atom_simple *atom_array; - int j; - char strfloat[256], strnull[256]; - sprintf(strfloat, "float"); - sprintf(strnull, "null"); - atom_array = malloc(sizeof(atom_simple)*argc); - MonoClass *c = mono_class_from_name (x->imagePureData, "PureData", "Atom"); - atoms = mono_array_new (x->domain, c, argc); - for (j=0; ja_type) - { - case A_FLOAT: - atom_array[j].a_type = A_S_FLOAT; - atom_array[j].float_value = (double) atom_getfloat(argv+j); - atom_array[j].string_value = mono_string_new (x->domain, strfloat); - break; - case A_SYMBOL: - atom_array[j].a_type = A_S_SYMBOL; - strsymbol = atom_getsymbol(argv+j); - atom_array[j].string_value = mono_string_new (x->domain, strsymbol->s_name); - atom_array[j].float_value = 0; - break; - default: - atom_array[j].a_type = A_S_NULL; - atom_array[j].float_value = 0; - atom_array[j].string_value = mono_string_new (x->domain, strnull); - } - mono_array_set (atoms, atom_simple , j, atom_array[j]); - } - - args[0] = atoms; - mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); - break; - } - } - return; - } - } - if (x->selectors[i].func == 0) - i = MAX_SELECTORS; - } - error("clr: selector not recognized"); -} - -// this function is called by mono when it wants to register a selector callback -void registerMonoMethod(void *x1, MonoString *selectorString, MonoString *methodString, int type) -{ - - char *selCstring, *metCstring; - MonoMethod *met; - t_clr *x; - int this_selector, i; - //int ret; - - - selCstring = mono_string_to_utf8 (selectorString); - metCstring = mono_string_to_utf8 (methodString); - - x = (t_clr *)x1; - - //ret = 0; - met = 0; - findMonoMethod( x->klass, metCstring, &met); - - if (!met) - { - error("method not found!"); - return; - } - - //post("registerMonoMethod: associating %s to %s", selCstring, metCstring); - - if (selectorString->length == 0) - { - switch (type) - { - case 1: // float - x->manageFloat = met; - break; - case 2: // string - x->manageSymbol = met; - break; - case 3: // list - x->manageList = met; - break; - case 4: // bang - x->manageBang = met; - break; - } - } - - this_selector = MAX_SELECTORS; - for (i = 0; i < MAX_SELECTORS; i++) - { - if (x->selectors[i].func == 0) - { - // i found the first empty space - this_selector = i; - i = MAX_SELECTORS; - } - - } - if (this_selector == MAX_SELECTORS) - { - error("not enough space for selectors! MAX_SELECTORS = %i", MAX_SELECTORS); - return; - } - - x->selectors[this_selector].sel = selCstring; - x->selectors[this_selector].func = met; - x->selectors[this_selector].type = type; - - class_addmethod(clr_class, (t_method)clr_manage_list, gensym(selCstring), A_GIMME, 0); - - -} - -// this function is called by mono when it wants to create a new inlet -void createInlet(void *x1, MonoString *selectorString, int type) -{ - // public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5}; - char *selCstring; - char typeString[256]; - t_clr *x; - - selCstring = mono_string_to_utf8 (selectorString); - x = (t_clr *)x1; - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - switch (type) - { - case 1: - sprintf(typeString, "float"); - break; - case 2: - sprintf(typeString, "symbol"); - break; - case 3: - sprintf(typeString, "list"); - break; - case 4: - sprintf(typeString, "bang"); - break; - default: - sprintf(typeString, ""); - break; - } - // create the inlet - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym(typeString), gensym(selCstring)); -} - -// this function is called by mono when it wants to create a new outlet -void createOutlet(void *x1, int type) -{ - t_clr *x; - int i = 0; - char typeString[256]; - x = (t_clr *)x1; - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - // public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5}; - switch (type) - { - case 1: - sprintf(typeString, "float"); - break; - case 2: - sprintf(typeString, "symbol"); - break; - case 3: - sprintf(typeString, "list"); - break; - case 4: - sprintf(typeString, "bang"); - break; - default: - sprintf(typeString, ""); - break; - } - - while (i < MAX_OUTLETS) - { - if (x->outlets[i].outlet_pointer == 0) - { - // empty space found! - x->outlets[i].outlet_pointer = outlet_new(&x->x_obj, gensym(typeString)); - return; - } - i++; - } - error("the maximum number of outlets has been reached (%i)", MAX_OUTLETS); - -} - -// out to outlet -void out2outlet(void *x1, int outlet, int atoms_length, MonoArray *array) -{ - t_clr *x; - x = (t_clr *)x1; - t_atom *lista; - atom_simple *atoms; - int n; - if (x->loaded == 0) - { - error("assembly not specified"); - return; - } - if ((outlet>MAX_OUTLETS) || (outlet<0)) - { - error("outlet number out of range, max is %i", MAX_OUTLETS); - return; - } - if (x->outlets[outlet].outlet_pointer == 0) - { - error("outlet %i not registered", outlet); - return; - } - lista = (t_atom *) malloc(sizeof(t_atom) * atoms_length); - atoms = (atom_simple *) malloc(sizeof(atom_simple) * atoms_length); - for (n=0; noutlets[outlet].outlet_pointer, - gensym("list") , - atoms_length, - lista); - free(lista); -} - -// this function is called by mono when it wants post messages to pd -void post2pd(MonoString *mesString) -{ - - char *mesCstring; - mesCstring = mono_string_to_utf8 (mesString); - post(mesCstring); - -} - -// this function is called by mono when it wants to post errors to pd -void error2pd(MonoString *mesString) -{ - - char *mesCstring; - mesCstring = mono_string_to_utf8 (mesString); - error(mesCstring); -} -/* -//void ext_class_addbang(const char *funcName) -void ext_class_addbang(t_method funcName) -{ -// class_addbang(clr_class, (t_method)clr_bang); - class_addbang(clr_class, funcName); -}*/ - -void *clr_new(t_symbol *s, int argc, t_atom *argv) -{ - - int i; - time_t a; - t_clr *x = (t_clr *)pd_new(clr_class); - - char strtmp[256]; - x->manageBang = 0; - x->manageSymbol = 0; - x->manageFloat = 0; - x->manageList = 0; - - if (argc==0) - { - x->loaded = 0; - error("clr: you must provide a class name as the first argument"); - return (x); - } - x->loaded = 1; - x->assemblyname = atom_gensym(argv); - - if (argc<2) - { - // only main class passed - // filename by default - sprintf(strtmp, "%s.dll", x->assemblyname->s_name); - x->filename = gensym(strtmp); -printf(" used did not specified filename, I guess it is %s\n", strtmp); - } else - { - x->filename = atom_gensym(argv+1); - } - - // load mono, init the needed vars - mono_load(x, argc, argv); - - return (x); -} - -void clr_setup(void) -{ - clr_class = class_new(gensym("clr"), (t_newmethod)clr_new, - (t_method)clr_free, sizeof(t_clr), CLASS_DEFAULT, A_GIMME, 0); - - class_addlist(clr_class, (t_method)clr_manage_list); - class_addbang(clr_class, (t_method)clr_bang); - class_addsymbol(clr_class, (t_method)clr_symbol); - class_addfloat(clr_class, (t_method)clr_float); - - mono_initialize(); - - // add mono to C hooks - mono_add_internal_call ("PureData.pd::RegisterSelector", registerMonoMethod); - mono_add_internal_call ("PureData.pd::ToOutlet", out2outlet); - mono_add_internal_call ("PureData.pd::PostMessage", post2pd); - mono_add_internal_call ("PureData.pd::ErrorMessage", error2pd); - mono_add_internal_call ("PureData.pd::CreateOutlet", createOutlet); - mono_add_internal_call ("PureData.pd::CreateInlet", createInlet); -} diff --git a/clr.cpp b/clr.cpp new file mode 100755 index 0000000..72185f0 --- /dev/null +++ b/clr.cpp @@ -0,0 +1,1150 @@ +// mono +extern "C" { +#include +#include +#include +#include +#include +#include +#include +} + +#ifdef _MSC_VER +#pragma warning(disable: 4091) +#endif +#include + +#include +#include +#include +#include // for _close + +#include + +#if 0 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//// OLD VERSION +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +#include +#include + + +#define MAX_SELECTORS 256 +#define MAX_OUTLETS 32 + +void *clr_new(t_symbol *s, int argc, t_atom *argv); + +typedef struct _clr +{ + t_object x_obj; // myself + t_outlet *l_out; + t_symbol *assemblyname; + t_symbol *filename; + int loaded; + // mono stuff + MonoAssembly *assembly; + MonoObject *obj; + MonoImage *image; + MonoMethod *method, *setUp, *manageBang, *manageSymbol, *manageFloat, *manageList; + MonoClass *klass; + int n; + + // TODO: dynamic memory allocation + selectorList selectors[MAX_SELECTORS]; + outletList outlets[MAX_OUTLETS]; + +} t_clr; + +// list of mono methods +typedef struct +{ + char *sel; // the selector + MonoMethod *func; // the function + int type; +// selectorList *next; // next element of the list +} selectorList; + +// list of outlets +typedef struct +{ + t_outlet *outlet_pointer; +// outletList *next; // next element of the list +} outletList; + +// simplyfied atom +typedef enum +{ + A_S_NULL=0, + A_S_FLOAT=1, + A_S_SYMBOL=2, +} t_atomtype_simple; + +typedef struct +{ + //t_atomtype_simple a_type; + int a_type; + float float_value; + MonoString *string_value; + +} atom_simple; + + + + +// mono functions + +static void mono_clean(t_clr *x) +{ + // clean up stuff + //mono_jit_cleanup (x->domain); + //mono_domain_free(x->domain); +} + +void registerMonoMethod(void *x, MonoString *selectorString, MonoString *methodString, int type); +void createInlet(void *x1, MonoString *selectorString, int type); +void createOutlet(void *x1, int type); +void out2outlet(void *x1, int outlet, int atoms_length, MonoArray *array); +void post2pd(MonoString *mesString); +void error2pd(MonoString *mesString); + + +// load the variables and init mono +static void mono_load(t_clr *x, int argc, t_atom *argv) +{ +// const char *file="D:\\Davide\\cygwin\\home\\Davide\\externalTest1.dll"; + //const char *file="External.dll"; + + MonoMethod *m = NULL, *ctor = NULL, *fail = NULL, *mvalues; + MonoClassField *classPointer; + gpointer iter; + gpointer *args; + int val; + int i,j; + int params; + t_symbol *strsymbol; + atom_simple *listparams; + + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + + // prepare the selectors list + for (i=0; iselectors[i].sel = 0; + x->selectors[i].func = 0; + } + // and the outlets list + for (i=0; ioutlets[i].outlet_pointer = 0; + } + + //mono_set_dirs (NULL, NULL); + //mono_config_parse (NULL); + + //mono_jit_init (random_name_str); +// x->domain = mono_domain_get(); + // all done without errors + x->loaded = 1; + +} + +/* +// call the method +static void clr_bang(t_clr *x) { + + gpointer args [2]; + int val; + MonoObject *result; + + val = x->n; + args [0] = &val; + + if (x->method) + { + result = mono_runtime_invoke (x->method, x->obj, args, NULL); + val = *(int*)mono_object_unbox (result); + x->n = val; + // outlet_float(x->l_out, (float) x->n); + } + + +} +*/ + +// finds a method from its name +void findMonoMethod( MonoClass *klass, char *function_name, MonoMethod **met) +{ + int trovato; + MonoMethod *m = NULL; + gpointer iter; + iter = NULL; + while (m = mono_class_get_methods (klass, &iter)) + { + if (strcmp (mono_method_get_name (m), function_name) == 0) + { + *met = m; +//printf("%s trovata\n", function_name); + return; + } + } +} + +void clr_free(t_clr *x) +{ + mono_clean(x); +} + +static void clr_method_bang(t_clr *x) +{ + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + if (x->manageBang) + { + mono_runtime_invoke (x->manageBang, x->obj, NULL, NULL); + } +} + +static void clr_method_symbol(t_clr *x, t_symbol *sl) +{ + gpointer args [1]; + MonoString *strmono; + strmono = mono_string_new (monodomain, sl->s_name); + args[0] = &strmono; + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + if (x->manageSymbol) + { + mono_runtime_invoke (x->manageSymbol, x->obj, args, NULL); + } +} + +static void clr_method_float(t_clr *x, float f) +{ + gpointer args [1]; + args [0] = &f; + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + if (x->manageFloat) + { + mono_runtime_invoke (x->manageFloat, x->obj, args, NULL); + } +} + +// here i look for the selector and call the right mono method +static void clr_method_list(t_clr *x, t_symbol *sl, int argc, t_atom *argv) +{ + gpointer args [2]; + int valInt; + float valFloat; + + int i; + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + + // check if a selector is present ! + //printf("clr_manage_list, got symbol = %s\n", sl->s_name); + if (strcmp("list", sl->s_name) == 0) + { + printf("lista senza selector"); + if (x->manageList) + { + gpointer args [1]; + MonoString *stringtmp; + double *floattmp; + t_atomtype_simple *typetmp; + t_symbol *strsymbol; + MonoArray *atoms; + atom_simple *atom_array; + int j; + char strfloat[256], strnull[256]; + sprintf(strfloat, "float"); + sprintf(strnull, "null"); + atom_array = malloc(sizeof(atom_simple)*argc); + atoms = mono_array_new (monodomain, clr_atom, argc); + for (j=0; ja_type) + { + case A_FLOAT: + atom_array[j].a_type = A_S_FLOAT; + atom_array[j].float_value = (double) atom_getfloat(argv+j); + atom_array[j].string_value = mono_string_new (monodomain, strfloat); + break; + case A_SYMBOL: + atom_array[j].a_type = A_S_SYMBOL; + strsymbol = atom_getsymbol(argv+j); + atom_array[j].string_value = mono_string_new (monodomain, strsymbol->s_name); + atom_array[j].float_value = 0; + break; + default: + atom_array[j].a_type = A_S_NULL; + atom_array[j].float_value = 0; + atom_array[j].string_value = mono_string_new (monodomain, strnull); + } + mono_array_set (atoms, atom_simple , j, atom_array[j]); + } + + args[0] = atoms; + mono_runtime_invoke (x->manageList, x->obj, args, NULL); + return; + } else + { + error("you did not specified a function to call for lists without selectors"); + return; + } + } + for (i=0; iselectors[i].sel, sl->s_name) == 0) + { + // I've found the selector! + if (x->selectors[i].func) + { + // ParametersType {None = 0, Float=1, Symbol=2, List=3}; + switch (x->selectors[i].type) + { + case 0: + mono_runtime_invoke (x->selectors[i].func, x->obj, NULL, NULL); + break; + case 1: + { + gpointer args [1]; + float val = atom_getfloat(argv); + args[0] = &val; + mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); + break; + } + case 2: + { + gpointer args [1]; + t_symbol *strsymbol; + MonoString *strmono; + strsymbol = atom_getsymbol(argv); + strmono = mono_string_new (monodomain, strsymbol->s_name); + args[0] = &strmono; + mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); + // memory leak ? + break; + } + case 3: + { + gpointer args [1]; + MonoString *stringtmp; + double *floattmp; + t_atomtype_simple *typetmp; + t_symbol *strsymbol; + MonoArray *atoms; + atom_simple *atom_array; + int j; + char strfloat[256], strnull[256]; + sprintf(strfloat, "float"); + sprintf(strnull, "null"); + atom_array = malloc(sizeof(atom_simple)*argc); + atoms = mono_array_new (monodomain, clr_atom, argc); + for (j=0; ja_type) + { + case A_FLOAT: + atom_array[j].a_type = A_S_FLOAT; + atom_array[j].float_value = (double) atom_getfloat(argv+j); + atom_array[j].string_value = mono_string_new (monodomain, strfloat); + break; + case A_SYMBOL: + atom_array[j].a_type = A_S_SYMBOL; + strsymbol = atom_getsymbol(argv+j); + atom_array[j].string_value = mono_string_new (monodomain, strsymbol->s_name); + atom_array[j].float_value = 0; + break; + default: + atom_array[j].a_type = A_S_NULL; + atom_array[j].float_value = 0; + atom_array[j].string_value = mono_string_new (monodomain, strnull); + } + mono_array_set (atoms, atom_simple , j, atom_array[j]); + } + + args[0] = atoms; + mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); + break; + } + } + return; + } + } + if (x->selectors[i].func == 0) + i = MAX_SELECTORS; + } + error("clr: selector not recognized"); +} + +// this function is called by mono when it wants to register a selector callback +void registerMonoMethod(void *x1, MonoString *selectorString, MonoString *methodString, int type) +{ + + char *selCstring, *metCstring; + MonoMethod *met; + t_clr *x; + int this_selector, i; + //int ret; + + + selCstring = mono_string_to_utf8 (selectorString); + metCstring = mono_string_to_utf8 (methodString); + + x = (t_clr *)x1; + + //ret = 0; + met = 0; + findMonoMethod( x->klass, metCstring, &met); + + if (!met) + { + error("method not found!"); + return; + } + + //post("registerMonoMethod: associating %s to %s", selCstring, metCstring); + + if (selectorString->length == 0) + { + switch (type) + { + case 1: // float + x->manageFloat = met; + break; + case 2: // string + x->manageSymbol = met; + break; + case 3: // list + x->manageList = met; + break; + case 4: // bang + x->manageBang = met; + break; + } + } + + this_selector = MAX_SELECTORS; + for (i = 0; i < MAX_SELECTORS; i++) + { + if (x->selectors[i].func == 0) + { + // i found the first empty space + this_selector = i; + i = MAX_SELECTORS; + } + + } + if (this_selector == MAX_SELECTORS) + { + error("not enough space for selectors! MAX_SELECTORS = %i", MAX_SELECTORS); + return; + } + + x->selectors[this_selector].sel = selCstring; + x->selectors[this_selector].func = met; + x->selectors[this_selector].type = type; + + class_addmethod(clr_class, (t_method)clr_method_list, gensym(selCstring), A_GIMME, 0); + + +} + +// this function is called by mono when it wants to create a new inlet +void createInlet(void *x1, MonoString *selectorString, int type) +{ + // public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5}; + char *selCstring; + char typeString[256]; + t_clr *x; + + selCstring = mono_string_to_utf8 (selectorString); + x = (t_clr *)x1; + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + switch (type) + { + case 1: + sprintf(typeString, "float"); + break; + case 2: + sprintf(typeString, "symbol"); + break; + case 3: + sprintf(typeString, "list"); + break; + case 4: + sprintf(typeString, "bang"); + break; + default: + sprintf(typeString, ""); + break; + } + // create the inlet + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym(typeString), gensym(selCstring)); +} + +// this function is called by mono when it wants to create a new outlet +void createOutlet(void *x1, int type) +{ + t_clr *x; + int i = 0; + char typeString[256]; + x = (t_clr *)x1; + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + // public enum ParametersType {None = 0, Float=1, Symbol=2, List=3, Bang=4, Generic=5}; + switch (type) + { + case 1: + sprintf(typeString, "float"); + break; + case 2: + sprintf(typeString, "symbol"); + break; + case 3: + sprintf(typeString, "list"); + break; + case 4: + sprintf(typeString, "bang"); + break; + default: + sprintf(typeString, ""); + break; + } + + while (i < MAX_OUTLETS) + { + if (x->outlets[i].outlet_pointer == 0) + { + // empty space found! + x->outlets[i].outlet_pointer = outlet_new(&x->x_obj, gensym(typeString)); + return; + } + i++; + } + error("the maximum number of outlets has been reached (%i)", MAX_OUTLETS); + +} + +// out to outlet +void out2outlet(void *x1, int outlet, int atoms_length, MonoArray *array) +{ + t_clr *x; + t_atom *lista; + atom_simple *atoms; + int n; + x = (t_clr *)x1; + if (x->loaded == 0) + { + error("assembly not specified"); + return; + } + if ((outlet>MAX_OUTLETS) || (outlet<0)) + { + error("outlet number out of range, max is %i", MAX_OUTLETS); + return; + } + if (x->outlets[outlet].outlet_pointer == 0) + { + error("outlet %i not registered", outlet); + return; + } + lista = (t_atom *) malloc(sizeof(t_atom) * atoms_length); + atoms = (atom_simple *) malloc(sizeof(atom_simple) * atoms_length); + for (n=0; noutlets[outlet].outlet_pointer, + gensym("list") , + atoms_length, + lista); + free(lista); +} + +// this function is called by mono when it wants post messages to pd +void post2pd(MonoString *mesString) +{ + + char *mesCstring; + mesCstring = mono_string_to_utf8 (mesString); + post(mesCstring); + +} + +// this function is called by mono when it wants to post errors to pd +void error2pd(MonoString *mesString) +{ + + char *mesCstring; + mesCstring = mono_string_to_utf8 (mesString); + error(mesCstring); +} +/* +//void ext_class_addbang(const char *funcName) +void ext_class_addbang(t_method funcName) +{ +// class_addbang(clr_class, (t_method)clr_bang); + class_addbang(clr_class, funcName); +}*/ + +void *clr_new(t_symbol *s, int argc, t_atom *argv) +{ + + int i; + time_t a; + t_clr *x = (t_clr *)pd_new(clr_class); + + char strtmp[256]; + x->manageBang = 0; + x->manageSymbol = 0; + x->manageFloat = 0; + x->manageList = 0; + + if (argc==0) + { + x->loaded = 0; + error("clr: you must provide a class name as the first argument"); + return (x); + } + x->loaded = 1; + x->assemblyname = atom_gensym(argv); + + if (argc<2) + { + // only main class passed + // filename by default + sprintf(strtmp, "%s.dll", x->assemblyname->s_name); + x->filename = gensym(strtmp); + printf(" used did not specified filename, I guess it is %s\n", strtmp); + } else + { + x->filename = atom_gensym(argv+1); + } + + x->obj = mono_object_new (monodomain, x->klass); + + // load mono, init the needed vars +// mono_load(x, argc, argv); + // now call the class constructor + if (ctor) + { + args = malloc(sizeof(gpointer)*params); + listparams = malloc(sizeof(atom_simple)*params); + for (j=2; ja_type) + { + case A_FLOAT: + listparams[j-2].a_type = A_S_FLOAT; + listparams[j-2].float_value = (double) atom_getfloat(argv+j); + args[j-2] = &(listparams[j-2].float_value); + break; + case A_SYMBOL: + listparams[j-2].a_type = A_S_SYMBOL; + strsymbol = atom_getsymbol(argv+j); + listparams[j-2].string_value = mono_string_new (monodomain, strsymbol->s_name); + args[j-2] = listparams[j-2].string_value; + break; + } + } + mono_runtime_invoke (ctor, x->obj, args, NULL); + free(listparams); + free(args); + } else + { + error("%s doesn't have a constructor with %i parameters!",x->assemblyname->s_name, params); + } + + + return (x); +} + +#endif + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//// NEW VERSION +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static MonoDomain *monodomain; +static MonoClass *clr_atom,*clr_symbol; +static MonoClassField *clr_symbol_ptr; +//static MonoMethod *clr_symbol_ctor; +static MonoMethodDesc *clr_desc_main,*clr_desc_ctor; +static MonoMethodDesc *clr_desc_bang,*clr_desc_float,*clr_desc_symbol,*clr_desc_pointer,*clr_desc_list,*clr_desc_anything; + +typedef std::map ClrMethodMap; + +// this is the class structure +// holding the pd and mono class +// and our CLR method pointers +typedef struct +{ + t_class *pd_class; + MonoClass *mono_class; + MonoClassField *mono_obj_field; + MonoMethod *mono_ctor; + MonoMethod *method_bang,*method_float, *method_symbol,*method_list,*method_pointer,*method_anything; +// ClrMethodMap *methods; +} t_clr_class; + +typedef std::map ClrMap; +// this holds the class name to class structure association +static ClrMap clr_map; + +// this is the class to be setup (while we are in the CLR static Main method) +static t_clr_class *clr_setup_class = NULL; + +// this is the class instance object structure +typedef struct +{ + t_object pd_obj; // myself + t_clr_class *clr_clss; // pointer to our class structure + MonoObject *mono_obj; +} t_clr; + + + +static void clr_method_bang(t_clr *x) +{ + assert(x && x->clr_clss && x->clr_clss->method_bang); + mono_runtime_invoke(x->clr_clss->method_bang,x->mono_obj,NULL,NULL); +} + +static void clr_method_float(t_clr *x,t_float f) +{ + assert(x && x->clr_clss && x->clr_clss->method_float); + gpointer args = &f; + mono_runtime_invoke(x->clr_clss->method_float,x->mono_obj,&args,NULL); +} + +static void clr_method_symbol(t_clr *x,t_symbol *s) +{ + assert(x && x->clr_clss && x->clr_clss->method_symbol); + MonoObject *symobj = mono_object_new(monodomain,clr_symbol); +// gpointer args = &s; +// mono_runtime_invoke(clr_symbol_ctor,symobj,&args,NULL); + // setting the field directly doesn't seem to work?! + mono_field_set_value(symobj,clr_symbol_ptr,s); + gpointer args = symobj; + mono_runtime_invoke(x->clr_clss->method_symbol,x->mono_obj,&args,NULL); +} + +static void clr_method_list(t_clr *x,int argc, t_atom *argv) +{ + assert(x && x->clr_clss && x->clr_clss->method_list); +} + +static void clr_method_pointer(t_clr *x,t_gpointer *ptr) +{ + assert(x && x->clr_clss && x->clr_clss->method_pointer); +} + +static void clr_method_anything(t_clr *x,t_symbol *sl, int argc, t_atom *argv) +{ +#if 0 + assert(x && x->clr_clss); + ClrMethodMap *methods = x->clr_clss->methods; + if(methods) { + ClrMethodMap::iterator it = methods->find(sl); + if(it != methods->end()) { + // \TODO call m + return; + } + } + if(x->clr_clss->method_anything) { + // \TODO call methodanything + } + else + post("CLR - no method for %s found",sl->s_name); +#else + assert(x && x->clr_clss && x->clr_clss->method_anything); +#endif +} + + +// this function is called by mono when it wants post messages to pd +static void PD_Post(MonoString *str) +{ + post("%s",mono_string_to_utf8(str)); +} + +// this function is called by mono when it wants post messages to pd +static void PD_PostError(MonoString *str) +{ + error("%s",mono_string_to_utf8(str)); +} + +// this function is called by mono when it wants post messages to pd +static void PD_PostBug(MonoString *str) +{ + bug("%s",mono_string_to_utf8(str)); +} + +// this function is called by mono when it wants post messages to pd +static void PD_PostVerbose(int lvl,MonoString *str) +{ + verbose(lvl,"%s",mono_string_to_utf8(str)); +} + +static void *PD_GenSym(MonoString *str) +{ + return gensym(mono_string_to_utf8(str)); +} + +static MonoString *PD_EvalSym(MonoObject *symobj) +{ + t_symbol *sym; + mono_field_get_value(symobj,clr_symbol_ptr,&sym); + return mono_string_new(monodomain,sym->s_name); +} + + +#if 0 +// this function is called by mono when it wants post messages to pd +static void PD_AddMethod(MonoObject *symobj,MonoObject *obj) +{ + assert(clr_setup_class); + +// char *tag = mono_string_to_utf8(str); +// post("register method %s",tag); + t_symbol *sym; + mono_field_get_value(symobj,clr_symbol_ptr,&sym); + + // \TODO convert from obj + MonoMethod *m = NULL; + + if(sym == &s_bang) { + if(!clr_setup_class->method_bang) + class_addbang(clr_setup_class->pd_class,clr_method_bang); + clr_setup_class->method_bang = m; + } + else if(sym == &s_float) { + if(!clr_setup_class->method_bang) + class_addfloat(clr_setup_class->pd_class,clr_method_float); + clr_setup_class->method_bang = m; + } + else if(sym == &s_symbol) { + if(!clr_setup_class->method_symbol) + class_addsymbol(clr_setup_class->pd_class,clr_method_symbol); + clr_setup_class->method_symbol = m; + } + else if(sym == &s_list) { + if(!clr_setup_class->method_list) + class_addlist(clr_setup_class->pd_class,clr_method_list); + clr_setup_class->method_list = m; + } + else if(sym == &s_pointer) { + if(!clr_setup_class->method_pointer) + class_addpointer(clr_setup_class->pd_class,clr_method_pointer); + clr_setup_class->method_pointer = m; + } + else if(sym == &s_) { + if(!clr_setup_class->method_anything && !clr_setup_class->methods) // only register once! + class_addanything(clr_setup_class->pd_class,clr_method_anything); + clr_setup_class->method_anything = m; + } + else { + if(!clr_setup_class->methods) { + // no methods yet + clr_setup_class->methods = new ClrMethodMap; + if(!clr_setup_class->method_anything) // only register once! + class_addanything(clr_setup_class->pd_class,clr_method_anything); + } + + // add tag to map + (*clr_setup_class->methods)[sym] = m; + } +} +#endif + +void *clr_new(t_symbol *classname, int argc, t_atom *argv) +{ + // find class name in map + ClrMap::iterator it = clr_map.find(classname); + if(it == clr_map.end()) { + error("CLR class %s not found",classname->s_name); + return NULL; + } + + t_clr_class *clss = it->second; + + // make instance + t_clr *x = (t_clr *)pd_new(clss->pd_class); + x->mono_obj = mono_object_new (monodomain,clss->mono_class); + if(!x->mono_obj) { + pd_free((t_pd *)x); + error("CLR class %s could not be instantiated",classname->s_name); + return NULL; + } + + // store class pointer + x->clr_clss = clss; + + // store our object pointer in External::ptr member + mono_field_set_value(x->mono_obj,clss->mono_obj_field,x); + + // ok, we have an object - look for constructor + if(clss->mono_ctor) { + // call static Main method + MonoObject *ret = mono_runtime_invoke(clss->mono_ctor,x->mono_obj,NULL,NULL); + if(ret) { + post("Warning: returned value from %s::.ctor ignored",classname->s_name); + // ??? do we have to mark ret as free? + } + } + else + post("Warning: no %s.Main method found",classname); + + return x; +} + +void clr_free(t_clr *x) +{ +} + +static int classloader(char *dirname, char *classname) +{ + t_clr_class *clr_class = NULL; + t_symbol *classsym; + MonoAssembly *assembly; + MonoImage *image; + MonoMethod *method; + + char dirbuf[MAXPDSTRING],*nameptr; + // search for classname.dll in the PD path + int fd; + if ((fd = open_via_path(dirname, classname, ".dll", dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) + // not found + goto bailout; + + // found + _close(fd); + + clr_class = (t_clr_class *)getbytes(sizeof(t_clr_class)); + +// clr_class->methods = NULL; + + // try to load assembly + char path[MAXPDSTRING]; + strcpy(path,dirname); + strcat(path,"/"); +// strcat(path,dirbuf); +// strcat(path,"/"); + strcat(path,nameptr); + + assembly = mono_domain_assembly_open(monodomain,path); + if(!assembly) { + error("clr: file %s couldn't be loaded!",path); + goto bailout; + } + + image = mono_assembly_get_image(assembly); + assert(image); + + // try to find class + // "" means no namespace + clr_class->mono_class = mono_class_from_name(image,"",classname); + if(!clr_class->mono_class) { + error("Can't find %s class in %s\n",classname,mono_image_get_filename(image)); + goto bailout; + } + + clr_class->mono_obj_field = mono_class_get_field_from_name(clr_class->mono_class,"ptr"); + assert(clr_class->mono_obj_field); + + // ok + + post("CLR class %s loaded",classname); + + // make new class (with classname) + classsym = gensym(classname); + clr_class->pd_class = class_new(classsym,(t_newmethod)clr_new,(t_method)clr_free, sizeof(t_clr), CLASS_DEFAULT, A_GIMME, 0); + + // find static Main method + + method = mono_method_desc_search_in_class(clr_desc_main,clr_class->mono_class); + if(method) { + // set current class + clr_setup_class = clr_class; + + // call static Main method + MonoObject *ret = mono_runtime_invoke(method,NULL,NULL,NULL); + + // unset current class + clr_setup_class = NULL; + + if(ret) { + post("CLR - Warning: returned value from %s.Main ignored",classname); + // ??? do we have to mark ret as free? + } + } + else + post("CLR - Warning: no %s.Main method found",classname); + + // find and save constructor + clr_class->mono_ctor = mono_method_desc_search_in_class(clr_desc_ctor,clr_class->mono_class); + + // find && register methods + if((clr_class->method_bang = mono_method_desc_search_in_class(clr_desc_bang,clr_class->mono_class)) != NULL) + class_addbang(clr_class->pd_class,clr_method_bang); + if((clr_class->method_float = mono_method_desc_search_in_class(clr_desc_float,clr_class->mono_class)) != NULL) + class_addfloat(clr_class->pd_class,clr_method_float); + if((clr_class->method_symbol = mono_method_desc_search_in_class(clr_desc_symbol,clr_class->mono_class)) != NULL) + class_addsymbol(clr_class->pd_class,clr_method_symbol); +// if((clr_class->method_pointer = mono_class_get_method_from_name(clr_class->mono_class,"MethodPointer",1)) != NULL) + if((clr_class->method_pointer = mono_method_desc_search_in_class(clr_desc_pointer,clr_class->mono_class)) != NULL) + class_addpointer(clr_class->pd_class,clr_method_pointer); + if((clr_class->method_list = mono_method_desc_search_in_class(clr_desc_list,clr_class->mono_class)) != NULL) + class_addlist(clr_class->pd_class,clr_method_list); + if((clr_class->method_anything = mono_method_desc_search_in_class(clr_desc_anything,clr_class->mono_class)) != NULL) + class_addanything(clr_class->pd_class,clr_method_anything); + + + // put into map + clr_map[classsym] = clr_class; + + post("Loaded class %s OK",classname); + + return 1; + +bailout: + if(clr_class) freebytes(clr_class,sizeof(t_clr_class)); + + return 0; +} + +extern "C" +#ifdef _MSC_VER +__declspec(dllexport) +#endif +void clr_setup(void) +{ +#ifdef _WIN32 + // set mono paths + const char *monopath = getenv("MONO_PATH"); + if(!monopath) { + error("CLR - Please set the MONO_PATH environment variable to the folder of your MONO installation - CLR not loaded!"); + return; + } + + char tlib[256],tconf[256]; + strcpy(tlib,monopath); + strcat(tlib,"/lib"); + strcpy(tconf,monopath); + strcat(tconf,"/etc"); + mono_set_dirs(tlib,tconf); +#endif + + monodomain = mono_jit_init("PureData"); + if(monodomain) { + /* + // add mono to C hooks + mono_add_internal_call ("PureData.pd::RegisterSelector", registerMonoMethod); + mono_add_internal_call ("PureData.pd::ToOutlet", out2outlet); + mono_add_internal_call ("PureData.pd::PostMessage", post2pd); + mono_add_internal_call ("PureData.pd::ErrorMessage", error2pd); + mono_add_internal_call ("PureData.pd::CreateOutlet", createOutlet); + mono_add_internal_call ("PureData.pd::CreateInlet", createInlet); + */ +// mono_add_internal_call ("PureData.Core::AddMethod", PD_AddMethod); + + mono_add_internal_call("PureData.Core::Post",(const void *)PD_Post); + mono_add_internal_call("PureData.Core::PostError",(const void *)PD_PostError); + mono_add_internal_call("PureData.Core::PostBug",(const void *)PD_PostBug); + mono_add_internal_call("PureData.Core::PostVerbose",(const void *)PD_PostVerbose); + + mono_add_internal_call("PureData.Core::GenSym", PD_GenSym); + mono_add_internal_call("PureData.Core::EvalSym", PD_EvalSym); + + + MonoAssembly *assembly = mono_domain_assembly_open (monodomain, "PureData.dll"); + if(!assembly) { + error("clr: assembly PureData.dll not found!"); + return; + } + + MonoImage *image = mono_assembly_get_image(assembly); + assert(image); + + // load important classes + clr_atom = mono_class_from_name(image,"PureData","Atom"); + assert(clr_atom); + clr_symbol = mono_class_from_name(image,"PureData","Symbol"); + assert(clr_symbol); + clr_symbol_ptr = mono_class_get_field_from_name(clr_symbol,"ptr"); + assert(clr_symbol_ptr); +// MonoMethodDesc *d = mono_method_desc_new("::.ctor(System.IntPtr)",FALSE); +// assert(d); +// clr_symbol_ctor = mono_method_desc_search_in_class(d,clr_symbol); +// assert(clr_symbol_ctor); + + clr_desc_main = mono_method_desc_new("::Main",FALSE); + assert(clr_desc_main); + clr_desc_ctor = mono_method_desc_new("::.ctor",FALSE); + assert(clr_desc_ctor); + + clr_desc_bang = mono_method_desc_new(":MethodBang",FALSE); + assert(clr_desc_bang); + clr_desc_float = mono_method_desc_new(":MethodFloat",FALSE); + assert(clr_desc_float); + clr_desc_symbol = mono_method_desc_new(":MethodSymbol",FALSE); + assert(clr_desc_symbol); + clr_desc_pointer = mono_method_desc_new(":MethodPointer",TRUE); + assert(clr_desc_pointer); + clr_desc_list = mono_method_desc_new(":MethodList",TRUE); + assert(clr_desc_list); + clr_desc_anything = mono_method_desc_new(":MethodAnything",TRUE); + assert(clr_desc_anything); + + // install loader hook + sys_loader(classloader); + + // ready! + post("CLR - (c) Davide Morelli, Thomas Grill"); + } + else + error("clr: mono domain couldn't be initialized!"); +} diff --git a/test-clr.pd b/test-clr.pd index 87bf798..6454fc5 100755 --- a/test-clr.pd +++ b/test-clr.pd @@ -1,53 +1,12 @@ -#N canvas 73 31 760 568 12; -#X obj 49 51 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X floatatom 65 70 5 0 0 0 - - -; -#X symbolatom 80 93 10 0 0 0 - - -; -#X text 146 66 simple messages; -#X msg 221 95 sel1; -#X msg 235 118 sel2; -#X text 282 107 selectors; -#X msg 244 161 selFloat \$1; -#X obj 247 142 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 0 1; -#X obj 227 263 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144 --1 -1 0 1; -#X text 224 242 mapped to selFloat; -#X msg 94 210 selGenericList 12 a 0.5 b; -#X text 93 188 complex list; -#X obj 82 297 print; -#X text 43 329 arguments: Class name \, Filename; -#X obj 438 353 clr Counter External.dll 2; -#X obj 83 267 clr External; -#X text 43 345 you omit filename if is the same as classname; -#X text 40 411 you can pass arguments; -#X text 39 431 in this case you must provide filename too; -#X floatatom 438 392 5 0 0 0 - - -; -#X floatatom 438 302 5 0 0 0 - - -; -#X msg 510 299 init 0; -#X text 36 453 the parameter is the initial value of the counter; -#X floatatom 641 320 5 0 0 0 - - -; -#X text 408 244 this external sums the value passed in the left inlet -with the stored one; -#X obj 411 305 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 --1; -#X text 287 3 more than one class can be compiled in the same assembly -; -#X text 37 477 NB: a class corresponding constructor must exist; -#X msg 309 210 1 2 3 a b c; -#X connect 0 0 16 0; -#X connect 1 0 16 0; -#X connect 2 0 16 0; -#X connect 4 0 16 0; -#X connect 5 0 16 0; -#X connect 7 0 16 0; -#X connect 8 0 7 0; -#X connect 9 0 16 1; -#X connect 11 0 16 0; -#X connect 15 0 20 0; -#X connect 16 0 13 0; -#X connect 21 0 15 0; -#X connect 22 0 15 0; -#X connect 24 0 15 1; -#X connect 26 0 15 0; -#X connect 29 0 16 0; +#N canvas 0 0 454 304 12; +#X obj 114 183 Counter; +#X floatatom 35 70 5 0 0 0 - - -; +#X msg 91 67 bang; +#X msg 145 69 1 2 3; +#X symbolatom 204 72 10 0 0 0 - - -; +#X msg 209 111 msg one 2 three; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; -- cgit v1.2.1