From 70fd0fd73aaa002d4d7e9841d8af105c4c80ddf4 Mon Sep 17 00:00:00 2001 From: Davide Morelli Date: Thu, 12 Jan 2006 09:22:35 +0000 Subject: checking in the external svn path=/trunk/externals/clr/; revision=4387 --- clr.c | 529 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ makefile | 32 ++++ makefile.darwin | 40 +++++ test-clr.pd | 38 ++++ 4 files changed, 639 insertions(+) create mode 100755 clr.c create mode 100755 makefile create mode 100755 makefile.darwin create mode 100755 test-clr.pd diff --git a/clr.c b/clr.c new file mode 100755 index 0000000..fc7b20b --- /dev/null +++ b/clr.c @@ -0,0 +1,529 @@ +/* +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; +// selectorList *next; // next element of the list +}; + +static t_class *clr_class; + +typedef struct _clr +{ + t_object x_obj; // myself + t_outlet *l_out; + // mono stuff + MonoDomain *domain; + MonoAssembly *assembly; + MonoObject *obj; + MonoMethod *method, *setUp; + MonoClass *klass; + int n; + + 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); + +} + +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 *x, int outlet, int type, unsigned char *val /* TODO */); +void post2pd(MonoString *mesString); +void error2pd(MonoString *mesString); + +// load the variables and init mono +static void mono_load(t_clr *x) +{ +// const char *file="D:\\Davide\\cygwin\\home\\Davide\\externalTest1.dll"; + const char *file="PureData.dll"; + MonoImage *image; + MonoMethod *m = NULL, *ctor = NULL, *fail = NULL, *mvalues; + gpointer iter; + gpointer args [1]; + int val; + int i; + double rnd; + int random_name_int; + char random_name_str[256]; + srand( (unsigned)time( NULL ) ); + rnd = rand()/((double)RAND_MAX + 1); + random_name_int =(int) (rnd * RAND_MAX); + sprintf(random_name_str, "%s-%i",file, random_name_int); + + // 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; + } + +printf("will load %s, random_name %s\n", file, random_name_str); + + x->domain = mono_jit_init (random_name_str); + + // 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); + + x->assembly = mono_domain_assembly_open (x->domain, file); + if (!x->assembly) + { + error("clr: assembly not found!"); + } + + image = mono_assembly_get_image (x->assembly); + + + x->klass = mono_class_from_name (image, "PureData", "External"); + if (!x->klass) { + error("Can't find MyType in assembly %s\n", mono_image_get_filename (image)); + //exit (1); + } + x->obj = mono_object_new (x->domain, x->klass); + mono_runtime_object_init (x->obj); + + /* 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) == 2) { + ctor = m; + } + } + } + + // call the base functions + if (x->setUp) + { + val = x; + args [0] = &val; + mono_runtime_invoke (x->setUp, x->obj, args, NULL); + post("SetUp() invoked"); + + } else + { + error("clr: the provided assembly is not valid! the SetUp function is missing"); + } + + +} + +/* +// 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); +} + +// 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; + // first i extract the first atom which should be a symbol + //post("clr_manage_list, got symbol = %s", sl->s_name); + + for (i=0; iselectors[i].sel, sl->s_name) == 0) + { + // I've found the selector! +printf("selector %s, func %s\n", sl->s_name, x->selectors[i].sel); + 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 *strmono; + t_symbol *strsymbol; + char *str; + MonoArray * arystr; + int j; +printf("preparo l'array\n"); + + arystr = mono_array_new (x->domain, mono_get_string_class (), argc); + for (j=0; jdomain, strsymbol->s_name); + mono_array_set (arystr, MonoString *, j, arg); + // gpointer + //mono_array_set (arystr, gint32 , j, ftmp); + + + } + args[0] = arystr; + + //args[0] = strings; +printf("mando a mono\n"); + mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); +printf("ho mandatao a mono\n"); + break; + } + } + + //result = mono_runtime_invoke (x->selectors[i].func, x->obj, args, NULL); + //val = *(int*)mono_object_unbox (result); + //x->n = val; + 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); + + 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; + + 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; + + // 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 type, unsigned char *val /* TODO */) +{ + t_clr *x; + x = (t_clr *)x1; + t_atom *lista; + + 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; + } +printf("ricevuto %i %i\n", val[0], val[1]); +if (val[0]==0x01) + printf("val[0]==0x00"); + + lista = (t_atom *) malloc(sizeof(t_atom) * 2); + SETFLOAT(lista, (float) val[0]); + SETFLOAT(lista+1, (float) val[1]); + outlet_anything(x->outlets[outlet].outlet_pointer, + gensym("list") , + 2, + 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); +// x->l_out = outlet_new(&x->x_obj, &s_list); +// x->l_out = outlet_new(&x->x_obj, gensym("float")); + + + + x->n = 0; + // load mono, init the needed vars + mono_load(x); + + 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_addbang(clr_class, (t_method)clr_bang); +// ext_class_addbang((t_method) clr_bang); + + class_addlist(clr_class, (t_method)clr_manage_list); + +} diff --git a/makefile b/makefile new file mode 100755 index 0000000..5ec27fe --- /dev/null +++ b/makefile @@ -0,0 +1,32 @@ +current: cygwin + +clean: ; rm -f *.dll *.o + + +cygwin: clr.dll + +.SUFFIXES: .dll + + +# where are the PD header files? +# leave it blank if it is a system directory (like /usr/local/include), +# since gcc 3.2 complains about it +PDPATH=/home/Davide + +LINUXCFLAGS = -DPD -O2 -mno-cygwin +#LINUXCFLAGS = -DPD -O2 -funroll-loops -fomit-frame-pointer \ +# -Wall -W -Wshadow -Wstrict-prototypes -Werror \ +# -Wno-unused -Wno-parentheses -Wno-switch + +LINUXINCLUDE = -I../../src -I$PDPATH + +MONOSRC = -ID:/Davide/cygwin/tmp/build_deps/include -ID:/Davide/cygwin/tmp/build_deps/include/glib-2.0 -ID:/Davide/cygwin/tmp/build_deps/lib/glib-2.0/include -ID:/Davide/cygwin/home/Davide/mono/include +MONOLIB = -LD:/Davide/cygwin/tmp/build_deps/lib -LD:/Davide/cygwin/home/Davide/mono/lib -lmono -lm -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv + +.c.dll: +# gcc $(LINUXCFLAGS) $(LINUXINCLUDE) `pkg-config --cflags --libs mono` -lm -ID:/Davide/cygwin/home/Davide/mono/include -LD:/Davide/cygwin/home/Davide/mono/lib $*.c + gcc $(LINUXCFLAGS) $(LINUXINCLUDE) $(MONOSRC) -o $*.o -c $*.c + gcc -export_dynamic -shared -mno-cygwin $(MONOLIB) -o $*.dll $*.o -lm pd.dll libmono.dll.a +# ld -export_dynamic $(MONOLIB) -o $*.dll $*.o -lm pd.dll +# strip --strip-unneeded $*.pd_linux +# rm $*.o diff --git a/makefile.darwin b/makefile.darwin new file mode 100755 index 0000000..54a8a01 --- /dev/null +++ b/makefile.darwin @@ -0,0 +1,40 @@ +current: pd_darwin + +clean: ; rm -f *.pd_linux *.o *.pd_darwin + + +# ----------------------- Mac OSX ----------------------- + +pd_darwin: clr.pd_darwin + +.SUFFIXES: .pd_darwin + + +# where are the PD header files? +# leave it blank if it is a system directory (like /usr/local/include), +# since gcc 3.2 complains about it +#PDPATH=/usr/local/src/pd/src +PDPATH=/Users/davide/Desktop/Pd-0.39-0.app/Contents/Resources/src/ + +# where is the PD executable? +#PD=/usr/local/bin/pd +PD=/Users/davide/Desktop/Pd-0.39-0.app/Contents/Resources/bin/pd +#PD=/Users/davidemorelli/Desktop/robaDavide/Pd-0.38-3.app/Contents/Resources/src/ + +CFLAGS=`pkg-config --cflags mono` +#LDFLAGS=`pkg-config --libs mono` +LDFLAGS=-L/sw/lib -L/sw/lib/pkgconfig/../../lib -lmono -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl -liconv + +DARWININCLUDE = -I../../src -I$(PDPATH) + +#DARWINCFLAGS = -DPD -O2 -Wall -W -Wshadow -Wstrict-prototypes \ +# -Wno-unused -Wno-parentheses -Wno-switch + +DARWINCFLAGS = -DPD -O2 + +.c.pd_darwin: + cc $(DARWINCFLAGS) $(DARWININCLUDE) $(CFLAGS) -o $*.o -c $*.c +# cc -bundle -bundle_loader $(PD) -multiply_defined supress $(LDFLAGS) -o $*.pd_darwin *.o + cc -bundle -bundle_loader $(PD) -flat_namespace $(LDFLAGS) -o $*.pd_darwin *.o +# cc -bundle -undefined suppress -flat_namespace -o $*.pd_darwin $(FANNLIB) *.o +# rm -f $*.o diff --git a/test-clr.pd b/test-clr.pd new file mode 100755 index 0000000..91f24dd --- /dev/null +++ b/test-clr.pd @@ -0,0 +1,38 @@ +#N canvas 0 0 726 474 12; +#X obj 97 383 clr; +#X obj 105 80 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 239 110 1 2 3; +#X msg 238 136 sel3 a b c; +#X msg 236 176 selFloat 0.5; +#X msg 247 221 selString ciao; +#X msg 247 263 selList 1 2 3; +#X msg 344 161 selFloat \$1; +#X obj 344 121 hsl 128 15 1 2 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X floatatom 360 142 5 0 0 0 - - -; +#X msg 242 59 sel1; +#X msg 240 87 sel2; +#X obj 428 260 hsl 128 15 1 2 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X text 424 239 2nd inlet mapped to selFloat; +#X obj 71 429 print a; +#X msg 239 297 selStringList abba baab caac dede; +#X msg 248 360 selFloatList 1 2 3 4; +#X msg 240 319 selStringList ego filose; +#X connect 0 0 14 0; +#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; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 7 0; +#X connect 8 0 9 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 0 1; +#X connect 15 0 0 0; +#X connect 16 0 0 0; +#X connect 17 0 0 0; -- cgit v1.2.1