Update of /cvsroot/pure-data/externals/clr In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20032
Added Files: clr.c makefile makefile.darwin test-clr.pd Log Message: checking in the external
--- NEW FILE: makefile --- 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
--- NEW FILE: test-clr.pd --- #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;
--- NEW FILE: makefile.darwin --- 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
--- NEW FILE: clr.c --- /* 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);
}