diff options
-rwxr-xr-x | clr.c | 529 | ||||
-rwxr-xr-x | makefile | 32 | ||||
-rwxr-xr-x | makefile.darwin | 40 | ||||
-rwxr-xr-x | test-clr.pd | 38 |
4 files changed, 639 insertions, 0 deletions
@@ -0,0 +1,529 @@ +/*
+just a dummy clr patch
+
+*/
+
+#include "m_pd.h"
+
+#include <time.h>
+#include <math.h>
+#include <stdlib.h>
+
+// mono
+#include <mono/jit/jit.h> +#include <mono/metadata/object.h> +#include <mono/metadata/environment.h> +#include <mono/metadata/assembly.h> +#include <mono/metadata/debug-helpers.h> +#include <string.h> +#include <stdlib.h> +
+#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; i<MAX_SELECTORS; i++) + { + x->selectors[i].sel = 0; + x->selectors[i].func = 0; + } + // and the outlets list + for (i=0; i<MAX_OUTLETS; i++) + { + x->outlets[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; i<MAX_SELECTORS; i++) + { + if (strcmp(x->selectors[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; j<argc; j++) + { + int * ftmp = malloc(sizeof(int)); + *ftmp = j; + strsymbol = atom_getsymbol(argv+j); + MonoString *arg = mono_string_new (x->domain, 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;
|