diff options
-rwxr-xr-x | Counter/Counter.cs | 38 | ||||
-rw-r--r-- | PureData/PureData.cs | 99 | ||||
-rwxr-xr-x | clr.cpp | 416 | ||||
-rwxr-xr-x | test-clr.pd | 17 |
4 files changed, 367 insertions, 203 deletions
diff --git a/Counter/Counter.cs b/Counter/Counter.cs index 13688e5..4cd1564 100755 --- a/Counter/Counter.cs +++ b/Counter/Counter.cs @@ -17,8 +17,10 @@ public class Counter: // that's the way to store args (don't just copy an AtomList instance!!) this.args = (PureData.Atom[])args; - AddInlet(s_list,new PureData.Symbol("list2")); +// AddInlet(s_list,new PureData.Symbol("list2")); + AddInlet(); AddInlet(ref farg); + AddInlet(); AddOutletBang(); } @@ -26,13 +28,15 @@ public class Counter: // returns void or ClassType private static ClassType Setup(Counter obj) { - Add(new MethodBang(obj.MyBang)); - Add(new MethodFloat(obj.MyFloat)); - Add(new MethodSymbol(obj.MySymbol)); - Add(new MethodList(obj.MyList)); - Add("set",new MethodList(obj.MySet)); - Add("send",new MethodList(obj.MySend)); - Add(new MethodAnything(obj.MyAnything)); + AddMethod(0,new MethodBang(obj.MyBang)); + AddMethod(0,new MethodFloat(obj.MyFloat)); + AddMethod(0,new MethodSymbol(obj.MySymbol)); + AddMethod(0,new MethodList(obj.MyList)); + AddMethod(0,"set",new MethodAnything(obj.MySet)); + AddMethod(0,"send",new MethodAnything(obj.MySend)); + AddMethod(0,new MethodAnything(obj.MyAnything)); + AddMethod(1,new MethodFloat(obj.MyFloat1)); + AddMethod(1,new MethodAnything(obj.MyAny1)); Post("Count.Main"); return ClassType.Default; @@ -50,6 +54,16 @@ public class Counter: Outlet(0,f); } + protected virtual void MyFloat1(float f) + { + Post("Count-FLOAT1 "+f.ToString()); + } + + protected virtual void MyAny1(int ix,PureData.Symbol s,PureData.AtomList l) + { + Post(ix.ToString()+": Count-ANY1 "+l.ToString()); + } + protected virtual void MySymbol(PureData.Symbol s) { Post("Count-SYMBOL "+s.ToString()); @@ -62,21 +76,21 @@ public class Counter: Outlet(0,l); } - protected virtual void MySet(PureData.AtomList l) + protected virtual void MySet(int ix,PureData.Symbol s,PureData.AtomList l) { Post("Count-SET "+l.ToString()); Outlet(0,new PureData.Symbol("set"),l); } - protected virtual void MySend(PureData.AtomList l) + protected virtual void MySend(int ix,PureData.Symbol s,PureData.AtomList l) { Send(new PureData.Symbol("receiver"),l); Send(new PureData.Symbol("receiver2"),(PureData.Atom[])l); } - protected virtual void MyAnything(PureData.Symbol s,PureData.AtomList l) + protected virtual void MyAnything(int ix,PureData.Symbol s,PureData.AtomList l) { - Post("Count-("+s.ToString()+") "+l.ToString()); + Post(ix.ToString()+": Count-("+s.ToString()+") "+l.ToString()); Outlet(0,s,l); } /* diff --git a/PureData/PureData.cs b/PureData/PureData.cs index 8dbac5b..ea0042b 100644 --- a/PureData/PureData.cs +++ b/PureData/PureData.cs @@ -13,30 +13,36 @@ namespace PureData [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static string SymEval(void *sym); + // -------------------------------------------------------------------------- + [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void AddInlet(void *obj,Symbol sel,Symbol to_sel); // map to data member - // \NOTE don't know if this is really safe since f must stay at its place (but it should, no?) [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void AddInlet(void *obj,ref float f); // map to data member - // \NOTE don't know if this is really safe since s must stay at its place (but it should, no?) [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void AddInlet(void *obj,ref Symbol s); // map to data member - // \NOTE don't know if this is really safe since s must stay at its place (but it should, no?) // [MethodImplAttribute (MethodImplOptions.InternalCall)] // internal extern static void AddInlet(void *obj,ref Pointer f); [MethodImplAttribute (MethodImplOptions.InternalCall)] - internal extern static void AddInlet(void *obj); // create proxy inlet + internal extern static void AddInlet(void *obj,Symbol type); // create proxy inlet (typed) + + [MethodImplAttribute (MethodImplOptions.InternalCall)] + internal extern static void AddInlet(void *obj); // create proxy inlet (anything) + + // -------------------------------------------------------------------------- [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void AddOutlet(void *obj,Symbol type); + // -------------------------------------------------------------------------- + [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void Outlet(void *obj,int n); @@ -58,6 +64,8 @@ namespace PureData [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void Outlet(void *obj,int n,Symbol s,Atom[] l); + // -------------------------------------------------------------------------- + [MethodImplAttribute (MethodImplOptions.InternalCall)] internal extern static void Bind(void *obj,Symbol dst); @@ -76,27 +84,39 @@ namespace PureData // -------------------------------------------------------------------------- - protected readonly static Symbol s__ = new Symbol(""); - protected readonly static Symbol s_bang = new Symbol("bang"); - protected readonly static Symbol s_float = new Symbol("float"); - protected readonly static Symbol s_symbol = new Symbol("symbol"); - protected readonly static Symbol s_pointer = new Symbol("pointer"); - protected readonly static Symbol s_list = new Symbol("list"); - protected readonly static Symbol s_anything = new Symbol("anything"); + protected readonly static Symbol _ = new Symbol(""); + protected readonly static Symbol _bang = new Symbol("bang"); + protected readonly static Symbol _float = new Symbol("float"); + protected readonly static Symbol _symbol = new Symbol("symbol"); + protected readonly static Symbol _pointer = new Symbol("pointer"); + protected readonly static Symbol _list = new Symbol("list"); + protected readonly static Symbol _anything = new Symbol("anything"); // -------------------------------------------------------------------------- [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Post(string message); + protected static void Post(string format,object arg0) { Post(String.Format(format,arg0)); } + protected static void Post(string format,object arg0,object arg1) { Post(String.Format(format,arg0,arg1)); } + protected static void Post(string format,object arg0,object arg1,object arg2) { Post(String.Format(format,arg0,arg1,arg2)); } + protected static void Post(string format,params object[] args) { Post(String.Format(format,args)); } + [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void PostError(string message); - [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void PostBug(string message); + protected static void PostError(string format,object arg0) { PostError(String.Format(format,arg0)); } + protected static void PostError(string format,object arg0,object arg1) { PostError(String.Format(format,arg0,arg1)); } + protected static void PostError(string format,object arg0,object arg1,object arg2) { PostError(String.Format(format,arg0,arg1,arg2)); } + protected static void PostError(string format,params object[] args) { PostError(String.Format(format,args)); } [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void PostVerbose(string message); + protected extern static void PostVerbose(int lvl,string message); + + protected static void PostVerbose(int lvl,string format,object arg0) { PostVerbose(lvl,String.Format(format,arg0)); } + protected static void PostVerbose(int lvl,string format,object arg0,object arg1) { PostVerbose(lvl,String.Format(format,arg0,arg1)); } + protected static void PostVerbose(int lvl,string format,object arg0,object arg1,object arg2) { PostVerbose(lvl,String.Format(format,arg0,arg1,arg2)); } + protected static void PostVerbose(int lvl,string format,params object[] args) { PostVerbose(lvl,String.Format(format,args)); } // -------------------------------------------------------------------------- @@ -105,49 +125,52 @@ namespace PureData protected delegate void MethodSymbol(Symbol s); protected delegate void MethodPointer(Pointer p); protected delegate void MethodList(AtomList lst); - protected delegate void MethodAnything(Symbol tag,AtomList lst); + protected delegate void MethodAnything(int inlet,Symbol tag,AtomList lst); + + // -------------------------------------------------------------------------- [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(MethodBang m); + protected extern static void AddMethod(int inlet,MethodBang m); [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(MethodFloat m); + protected extern static void AddMethod(int inlet,MethodFloat m); [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(MethodSymbol m); + protected extern static void AddMethod(int inlet,MethodSymbol m); [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(MethodPointer m); + protected extern static void AddMethod(int inlet,MethodPointer m); [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(MethodList m); + protected extern static void AddMethod(int inlet,MethodList m); [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(Symbol sel,MethodList m); + protected extern static void AddMethod(int inlet,Symbol sel,MethodAnything m); - protected static void Add(string sel,MethodList m) { Add(new Symbol(sel),m); } + protected static void AddMethod(int inlet,string sel,MethodAnything m) { AddMethod(inlet,new Symbol(sel),m); } [MethodImplAttribute (MethodImplOptions.InternalCall)] - protected extern static void Add(MethodAnything m); + protected extern static void AddMethod(int inlet,MethodAnything m); // -------------------------------------------------------------------------- - protected void AddInlet(Symbol sel,Symbol to_sel) { Internal.AddInlet(ptr,sel,to_sel); } - protected void AddInlet(ref float f) { Internal.AddInlet(ptr,ref f); } - protected void AddInlet(ref Symbol s) { Internal.AddInlet(ptr,ref s); } + protected void AddInlet(ref float f) { Internal.AddInlet(ptr,ref f); } // map to data member + protected void AddInlet(ref Symbol s) { Internal.AddInlet(ptr,ref s); } // map to data member // protected void AddInlet(ref Pointer p) { Internal.AddInlet(ptr,ref p); } // map to data member - protected void AddInlet() { Internal.AddInlet(ptr); } // create proxy inlet +// protected void AddInlet(Symbol type) { Internal.AddInlet(ptr,type); } // create typed inlet + protected void AddInlet() { Internal.AddInlet(ptr); } // create inlet responding to any message + protected void AddInlet(Symbol sel,Symbol to_sel) { Internal.AddInlet(ptr,sel,to_sel); } // redirect messages to defined selector // -------------------------------------------------------------------------- protected void AddOutlet(Symbol type) { Internal.AddOutlet(ptr,type); } - protected void AddOutletBang() { AddOutlet(s_bang); } - protected void AddOutletFloat() { AddOutlet(s_float); } - protected void AddOutletSymbol() { AddOutlet(s_symbol); } - protected void AddOutletPointer() { AddOutlet(s_pointer); } - protected void AddOutletList() { AddOutlet(s_list); } - protected void AddOutletAnything() { AddOutlet(s_anything); } + protected void AddOutletBang() { AddOutlet(_bang); } + protected void AddOutletFloat() { AddOutlet(_float); } + protected void AddOutletSymbol() { AddOutlet(_symbol); } + protected void AddOutletPointer() { AddOutlet(_pointer); } + protected void AddOutletList() { AddOutlet(_list); } + protected void AddOutletAnything() { AddOutlet(_anything); } // -------------------------------------------------------------------------- @@ -156,8 +179,8 @@ namespace PureData protected void Outlet(int n,Symbol s) { Internal.Outlet(ptr,n,s); } protected void Outlet(int n,Pointer p) { Internal.Outlet(ptr,n,p); } protected void Outlet(int n,Atom a) { Internal.Outlet(ptr,n,a); } - protected void Outlet(int n,AtomList l) { Internal.Outlet(ptr,n,s_list,l); } - protected void Outlet(int n,Atom[] l) { Internal.Outlet(ptr,n,s_list,l); } + protected void Outlet(int n,AtomList l) { Internal.Outlet(ptr,n,_list,l); } + protected void Outlet(int n,Atom[] l) { Internal.Outlet(ptr,n,_list,l); } protected void Outlet(int n,Symbol s,AtomList l) { Internal.Outlet(ptr,n,s,l); } protected void Outlet(int n,Symbol s,Atom[] l) { Internal.Outlet(ptr,n,s,l); } @@ -171,12 +194,12 @@ namespace PureData [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Send(Symbol sym,Atom a); - protected static void Send(Symbol sym) { Send(sym,s_bang,null); } + protected static void Send(Symbol sym) { Send(sym,_bang,null); } protected static void Send(Symbol sym,float f) { Send(sym,new Atom(f)); } protected static void Send(Symbol sym,Symbol s) { Send(sym,new Atom(s)); } protected static void Send(Symbol sym,Pointer p) { Send(sym,new Atom(p)); } - protected static void Send(Symbol sym,AtomList l) { Send(sym,s_list,l); } - protected static void Send(Symbol sym,Atom[] l) { Send(sym,s_list,l); } + protected static void Send(Symbol sym,AtomList l) { Send(sym,_list,l); } + protected static void Send(Symbol sym,Atom[] l) { Send(sym,_list,l); } [MethodImplAttribute (MethodImplOptions.InternalCall)] protected extern static void Send(Symbol sym,Symbol s,AtomList l); @@ -27,6 +27,7 @@ extern "C" { #include <map> #include <vector> +#include <list> #define CORELIB "PureData" #define DLLEXT "dll" @@ -51,25 +52,87 @@ struct AtomList // temporary workspace items -static MonoArray *clr_objarr_1,*clr_objarr_2; -static MonoObject *clr_obj_single,*clr_obj_symbol,*clr_obj_pointer,*clr_obj_atomlist; +static MonoArray *clr_objarr_1,*clr_objarr_3; +static MonoObject *clr_obj_int,*clr_obj_single,*clr_obj_symbol,*clr_obj_pointer,*clr_obj_atomlist; +static int *clr_val_int; static float *clr_val_single; static t_symbol **clr_val_symbol; static void **clr_val_pointer; static AtomList *clr_val_atomlist; +struct t_clr; struct Delegate { - operator bool() const { return methodinfo != NULL; } + enum Kind { k_bang,k_float,k_symbol,k_pointer,k_list,k_anything }; + + inline operator bool() const { return methodinfo != NULL; } MonoObject *methodinfo; MonoMethod *virtmethod; + Kind kind; + + inline void init(MonoObject *method,Kind k) + { + methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); + virtmethod = mono_object_get_virtual_method(methodinfo,clr_meth_invoke); + kind = k; + } + + inline MonoObject *operator()(MonoObject *obj,void *arg = NULL) const + { + gpointer args[2] = {obj,arg}; + assert(methodinfo); + MonoObject *exc; + mono_runtime_invoke(virtmethod,methodinfo,args,&exc); + return exc; + } + + inline MonoObject *invokeatom(MonoObject *obj,MonoObject *atom) const + { + mono_array_set(clr_objarr_1,void*,0,atom); + return operator()(obj,clr_objarr_1); + } + + inline MonoObject *operator()(MonoObject *obj,float f) const + { + *clr_val_single = f; + return invokeatom(obj,clr_obj_single); + } + + inline MonoObject *operator()(MonoObject *obj,t_symbol *s) const + { + *clr_val_symbol = s; + return invokeatom(obj,clr_obj_symbol); + } + + inline MonoObject *operator()(MonoObject *obj,t_gpointer *p) const + { + *clr_val_pointer = p; + return invokeatom(obj,clr_obj_pointer); + } + + inline MonoObject *operator()(MonoObject *obj,int argc,t_atom *argv) const + { + clr_val_atomlist->Set(argc,argv); + return invokeatom(obj,clr_obj_atomlist); + } + + inline MonoObject *operator()(MonoObject *obj,int inlet,t_symbol *s,int argc,t_atom *argv) const + { + *clr_val_int = inlet; + *clr_val_symbol = s; + clr_val_atomlist->Set(argc,argv); + mono_array_set(clr_objarr_3,void*,0,clr_obj_int); + mono_array_set(clr_objarr_3,void*,1,clr_obj_symbol); + mono_array_set(clr_objarr_3,void*,2,clr_obj_atomlist); + return operator()(obj,clr_objarr_3); + } }; typedef std::map<t_symbol *,Delegate> ClrMethodMap; - +typedef std::vector<ClrMethodMap *> ClrMethods; // this is the class structure // holding the pd and mono class @@ -82,7 +145,16 @@ struct t_clr_class MonoClassField *obj_field; // ptr field in PureData.External t_symbol *name; Delegate method_bang,method_float,method_symbol,method_pointer,method_list,method_anything; - ClrMethodMap *methods; // explicit method selectors + ClrMethods *methods; // explicit method selectors +}; + +static t_class *proxy_class; + +struct t_proxy +{ + t_object pd_obj; // myself + t_clr *parent; // parent object + int inlet; }; typedef std::map<t_symbol *,t_clr_class *> ClrMap; @@ -90,10 +162,14 @@ typedef std::map<t_symbol *,t_clr_class *> ClrMap; static ClrMap clr_map; typedef std::vector<t_outlet *> OutletArr; +typedef std::list<t_proxy *> ProxyList; // this is the class to be setup (while we are in the CLR static Main method) static t_clr_class *clr_setup_class = NULL; +// inlet index... must start with 0 every time a new object is made +static int clr_inlet; + // this is the class instance object structure struct t_clr { @@ -101,6 +177,7 @@ struct t_clr t_clr_class *clr_clss; // pointer to our class structure MonoObject *mono_obj; // the mono class instance OutletArr *outlets; + ProxyList *proxies; }; @@ -121,138 +198,117 @@ static void error_exc(char *txt,char *cname,MonoObject *exc) static void clr_method_bang(t_clr *x) { assert(x && x->clr_clss); - - const Delegate &d = x->clr_clss->method_bang; - assert(d); - - gpointer args[2] = {x->mono_obj,NULL}; - MonoObject *exc; - mono_runtime_invoke(d.virtmethod,d.methodinfo,args,&exc); + MonoObject *exc = x->clr_clss->method_bang(x->mono_obj); if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } static void clr_method_float(t_clr *x,t_float f) { assert(x && x->clr_clss); - - const Delegate &d = x->clr_clss->method_float; - assert(d); - - *clr_val_single = f; - mono_array_set(clr_objarr_1,void*,0,clr_obj_single); - - gpointer args[2] = {x->mono_obj,clr_objarr_1}; - MonoObject *exc; - mono_runtime_invoke(d.virtmethod,d.methodinfo,args,&exc); + MonoObject *exc = x->clr_clss->method_float(x->mono_obj,f); if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } static void clr_method_symbol(t_clr *x,t_symbol *s) { assert(x && x->clr_clss); - - const Delegate &d = x->clr_clss->method_symbol; - assert(d); - - *clr_val_symbol = s; - mono_array_set(clr_objarr_1,void*,0,clr_obj_symbol); - - gpointer args[2] = {x->mono_obj,clr_objarr_1}; - MonoObject *exc; - mono_runtime_invoke(d.virtmethod,d.methodinfo,args,&exc); + MonoObject *exc = x->clr_clss->method_symbol(x->mono_obj,s); if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } static void clr_method_pointer(t_clr *x,t_gpointer *p) { assert(x && x->clr_clss); - - const Delegate &d = x->clr_clss->method_pointer; - assert(d); - - *clr_val_pointer = p; - mono_array_set(clr_objarr_1,void*,0,clr_obj_pointer); - - gpointer args[2] = {x->mono_obj,clr_objarr_1}; - MonoObject *exc; - mono_runtime_invoke(d.virtmethod,d.methodinfo,args,&exc); + MonoObject *exc = x->clr_clss->method_pointer(x->mono_obj,p); if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } -static void clr_method_list(t_clr *x,t_symbol *l, int argc, t_atom *argv) +static void clr_method_list(t_clr *x,t_symbol *,int argc,t_atom *argv) { assert(x && x->clr_clss); - - const Delegate &d = x->clr_clss->method_list; - assert(d); - - clr_val_atomlist->Set(argc,argv); - mono_array_set(clr_objarr_1,void*,0,clr_obj_atomlist); - - gpointer args[2] = {x->mono_obj,clr_objarr_1}; - MonoObject *exc; - mono_runtime_invoke(d.virtmethod,d.methodinfo,args,&exc); + MonoObject *exc = x->clr_clss->method_symbol(x->mono_obj,argc,argv); if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } -static void clr_method_anything(t_clr *x,t_symbol *s,int argc,t_atom *argv) +static void call_anything(t_clr *x,int inlet,t_symbol *s,int argc,t_atom *argv) { assert(x && x->clr_clss); - const Delegate *d = NULL; - ClrMethodMap *methods = x->clr_clss->methods; - if(methods) { - ClrMethodMap::iterator it = methods->find(s); - if(it != methods->end()) d = &it->second; + const Delegate *d; + + ClrMethods *methods = x->clr_clss->methods; + if(methods && inlet < (int)methods->size()) { + ClrMethodMap *methmap = (*methods)[inlet]; + if(methmap) { + ClrMethodMap::iterator it = methmap->find(s); + if(it != methmap->end()) { + d = &it->second; + goto found; + } + + if(inlet) { + // search for NULL symbol pointer + it = methmap->find(NULL); + if(it != methmap->end()) { + d = &it->second; + goto found; + } + } + } } - gpointer args[2]; - args[0] = x->mono_obj; + // no selectors: general method + d = &x->clr_clss->method_anything; - if(d) { - // explicit selector + found: - clr_val_atomlist->Set(argc,argv); - mono_array_set(clr_objarr_1,void*,0,clr_obj_atomlist); - args[1] = clr_objarr_1; - } - else { - // general method - - d = &x->clr_clss->method_anything; - assert(d); + // we must have found something.... + assert(d); - *clr_val_symbol = s; - clr_val_atomlist->Set(argc,argv); - mono_array_set(clr_objarr_2,void*,0,clr_obj_symbol); - mono_array_set(clr_objarr_2,void*,1,clr_obj_atomlist); - args[1] = clr_objarr_2; + MonoObject *exc; + switch(d->kind) { + case Delegate::k_bang: + assert(argc == 0); + exc = (*d)(x->mono_obj); + break; + case Delegate::k_float: + assert(argc == 1 && argv[0].a_type == A_FLOAT); + exc = (*d)(x->mono_obj,argv[0].a_w.w_float); + break; + case Delegate::k_symbol: + assert(argc == 1 && argv[0].a_type == A_SYMBOL); + exc = (*d)(x->mono_obj,argv[0].a_w.w_symbol); + break; + case Delegate::k_pointer: + assert(argc == 1 && argv[0].a_type == A_POINTER); + exc = (*d)(x->mono_obj,argv[0].a_w.w_gpointer); + break; + case Delegate::k_list: + exc = (*d)(x->mono_obj,argc,argv); + break; + case Delegate::k_anything: + exc = (*d)(x->mono_obj,inlet,s,argc,argv); + break; + default: + assert(false); } - MonoObject *exc; - mono_runtime_invoke(d->virtmethod,d->methodinfo,args,&exc); if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); } -// this function is called by mono when it wants post messages to pd +static void clr_method_anything(t_clr *x,t_symbol *s,int argc,t_atom *argv) { call_anything(x,0,s,argc,argv); } +static void clr_method_proxy(t_proxy *x,t_symbol *s,int argc,t_atom *argv) { call_anything(x->parent,x->inlet,s,argc,argv); } + 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)); @@ -270,70 +326,100 @@ static MonoString *PD_SymEval(t_symbol *sym) return mono_string_new(monodomain,sym->s_name); } -static void PD_AddBang(MonoObject *method) +static void PD_AddMethodHandler(int inlet,t_symbol *sym,MonoObject *method,Delegate::Kind kind) { assert(clr_setup_class); - Delegate &d = clr_setup_class->method_bang; + Delegate d; d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + d.kind = kind; + + ClrMethods *ms = clr_setup_class->methods; + if(!ms) + clr_setup_class->methods = ms = new ClrMethods; + + ClrMethodMap *m; + if(inlet >= (int)ms->size()) { + ms->resize(inlet+1,NULL); + (*ms)[inlet] = m = new ClrMethodMap; + } + else + m = (*ms)[inlet]; + assert(m); + + // add tag to map + (*m)[sym] = d; } -static void PD_AddFloat(MonoObject *method) +static void PD_AddMethodSelector(int inlet,t_symbol *sym,MonoObject *method) { - assert(clr_setup_class); - Delegate &d = clr_setup_class->method_float; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + PD_AddMethodHandler(inlet,sym,method,Delegate::k_anything); } -static void PD_AddSymbol(MonoObject *method) +static void PD_AddMethodBang(int inlet,MonoObject *method) { - assert(clr_setup_class); - Delegate &d = clr_setup_class->method_symbol; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + if(inlet) + PD_AddMethodHandler(inlet,&s_bang,method,Delegate::k_bang); + else { + assert(clr_setup_class); + clr_setup_class->method_bang.init(method,Delegate::k_bang); + } } -static void PD_AddPointer(MonoObject *method) +static void PD_AddMethodFloat(int inlet,MonoObject *method) { - assert(clr_setup_class); - Delegate &d = clr_setup_class->method_pointer; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + if(inlet) + PD_AddMethodHandler(inlet,&s_float,method,Delegate::k_float); + else { + assert(clr_setup_class); + clr_setup_class->method_float.init(method,Delegate::k_float); + } } -static void PD_AddList(MonoObject *method) +static void PD_AddMethodSymbol(int inlet,MonoObject *method) { - assert(clr_setup_class); - Delegate &d = clr_setup_class->method_list; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + if(inlet) + PD_AddMethodHandler(inlet,&s_symbol,method,Delegate::k_symbol); + else { + assert(clr_setup_class); + clr_setup_class->method_symbol.init(method,Delegate::k_symbol); + } } -static void PD_AddSelector(t_symbol *sym,MonoObject *method) +static void PD_AddMethodPointer(int inlet,MonoObject *method) { - assert(clr_setup_class); - Delegate d; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + if(inlet) + PD_AddMethodHandler(inlet,&s_pointer,method,Delegate::k_pointer); + else { + assert(clr_setup_class); + clr_setup_class->method_pointer.init(method,Delegate::k_pointer); + } +} - if(!clr_setup_class->methods) - clr_setup_class->methods = new ClrMethodMap; - // add tag to map - (*clr_setup_class->methods)[sym] = d; +static void PD_AddMethodList(int inlet,MonoObject *method) +{ + if(inlet) + PD_AddMethodHandler(inlet,&s_list,method,Delegate::k_list); + else { + assert(clr_setup_class); + clr_setup_class->method_list.init(method,Delegate::k_list); + } } -static void PD_AddAnything(MonoObject *method) +static void PD_AddMethodAnything(int inlet,MonoObject *method) { - assert(clr_setup_class); - Delegate &d = clr_setup_class->method_anything; - d.methodinfo = mono_property_get_value(clr_prop_method,method,NULL,NULL); - d.virtmethod = mono_object_get_virtual_method(d.methodinfo,clr_meth_invoke); + if(inlet) + PD_AddMethodHandler(inlet,NULL,method,Delegate::k_anything); + else { + assert(clr_setup_class); + clr_setup_class->method_anything.init(method,Delegate::k_anything); + } } -static void PD_AddInlet(t_clr *obj,t_symbol *sel,t_symbol *to_sel) +static void PD_AddInletAlias(t_clr *obj,t_symbol *sel,t_symbol *to_sel) { + ++clr_inlet; assert(obj); t_inlet *in = inlet_new(&obj->pd_obj,&obj->pd_obj.ob_pd,sel,to_sel); assert(in); @@ -341,6 +427,7 @@ static void PD_AddInlet(t_clr *obj,t_symbol *sel,t_symbol *to_sel) static void PD_AddInletFloat(t_clr *obj,float *f) { + ++clr_inlet; assert(obj); t_inlet *in = floatinlet_new(&obj->pd_obj,f); assert(in); @@ -348,6 +435,7 @@ static void PD_AddInletFloat(t_clr *obj,float *f) static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) { + ++clr_inlet; assert(obj); t_inlet *in = symbolinlet_new(&obj->pd_obj,s); assert(in); @@ -356,18 +444,28 @@ static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) /* static void PD_AddInletPointer(t_clr *obj,t_gpointer *p) { + ++clr_inlet; assert(obj); t_inlet *in = pointerinlet_new(&obj->pd_obj,p); assert(in); } */ -static void PD_AddInletProxy(t_clr *obj) +static void PD_AddInletProxyTyped(t_clr *obj,t_symbol *type) { assert(obj); - // TODO implement + t_proxy *p = (t_proxy *)pd_new(proxy_class); + p->parent = obj; + p->inlet = ++clr_inlet; + if(!obj->proxies) obj->proxies = new ProxyList; + obj->proxies->push_back(p); + t_inlet *in = inlet_new(&obj->pd_obj,&p->pd_obj.ob_pd,type,type); + assert(in); } +static void PD_AddInletProxy(t_clr *obj) { PD_AddInletProxyTyped(obj,NULL); } + + static void PD_AddOutlet(t_clr *obj,t_symbol *type) { assert(obj); @@ -381,7 +479,7 @@ static void PD_OutletBang(t_clr *obj,int n) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); outlet_bang((*obj->outlets)[n]); } @@ -389,7 +487,7 @@ static void PD_OutletFloat(t_clr *obj,int n,float f) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); outlet_float((*obj->outlets)[n],f); } @@ -397,7 +495,7 @@ static void PD_OutletSymbol(t_clr *obj,int n,t_symbol *s) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); outlet_symbol((*obj->outlets)[n],s); } @@ -405,7 +503,7 @@ static void PD_OutletPointer(t_clr *obj,int n,t_gpointer *p) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); outlet_pointer((*obj->outlets)[n],p); } @@ -413,7 +511,7 @@ static void PD_OutletAtom(t_clr *obj,int n,t_atom l) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); t_outlet *out = (*obj->outlets)[n]; switch(l.a_type) { case A_FLOAT: outlet_float(out,l.a_w.w_float); break; @@ -428,7 +526,7 @@ static void PD_OutletAnything(t_clr *obj,int n,t_symbol *s,AtomList l) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); outlet_anything((*obj->outlets)[n],s,l.argc,l.argv); } @@ -436,7 +534,7 @@ static void PD_OutletAnything2(t_clr *obj,int n,t_symbol *s,MonoArray *l) { assert(obj); assert(obj->outlets); - assert(n >= 0 && n < obj->outlets->size()); + assert(n >= 0 && n < (int)obj->outlets->size()); // assert(mono_object_get_class(&l->obj) == clr_atom); outlet_anything((*obj->outlets)[n],s,mono_array_length(l),mono_array_addr(l,t_atom,0)); } @@ -463,6 +561,7 @@ static void PD_SendAnything2(t_symbol *dst,t_symbol *s,MonoArray *l) 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); @@ -488,10 +587,14 @@ void *clr_new(t_symbol *classname, int argc, t_atom *argv) mono_field_set_value(x->mono_obj,clss->obj_field,x); x->outlets = NULL; + x->proxies = NULL; // ok, we have an object - look for constructor if(clss->mono_ctor) { - AtomList al; + // reset inlet index + clr_inlet = 0; + + AtomList al; al.Set(argc,argv); gpointer args = &al; @@ -511,9 +614,14 @@ void *clr_new(t_symbol *classname, int argc, t_atom *argv) return x; } -void clr_free(t_clr *x) +void clr_free(t_clr *obj) { - if(x->outlets) delete x->outlets; + if(obj->outlets) delete obj->outlets; + + if(obj->proxies) { + for(ProxyList::iterator it = obj->proxies->begin(); it != obj->proxies->end(); ++it) pd_free((t_pd *)*it); + delete obj->proxies; + } } static int classloader(char *dirname, char *classname) @@ -613,7 +721,7 @@ static int classloader(char *dirname, char *classname) // make pd class clr_class->pd_class = class_new(classsym,(t_newmethod)clr_new,(t_method)clr_free, sizeof(t_clr), flags, A_GIMME, A_NULL); - // find && register methods + // register methods if(clr_class->method_bang) class_addbang(clr_class->pd_class,clr_method_bang); if(clr_class->method_float) @@ -698,21 +806,21 @@ void clr_setup(void) mono_add_internal_call("PureData.External::Post(string)",(const void *)PD_Post); mono_add_internal_call("PureData.External::PostError(string)",(const void *)PD_PostError); - mono_add_internal_call("PureData.External::PostBug(string)",(const void *)PD_PostBug); - mono_add_internal_call("PureData.External::PostVerbose(string)",(const void *)PD_PostVerbose); - - mono_add_internal_call("PureData.External::Add(PureData.External/MethodBang)", (const void *)PD_AddBang); - mono_add_internal_call("PureData.External::Add(PureData.External/MethodFloat)", (const void *)PD_AddFloat); - mono_add_internal_call("PureData.External::Add(PureData.External/MethodSymbol)", (const void *)PD_AddSymbol); - mono_add_internal_call("PureData.External::Add(PureData.External/MethodPointer)", (const void *)PD_AddPointer); - mono_add_internal_call("PureData.External::Add(PureData.External/MethodList)", (const void *)PD_AddList); - mono_add_internal_call("PureData.External::Add(PureData.Symbol,PureData.External/MethodList)", (const void *)PD_AddSelector); - mono_add_internal_call("PureData.External::Add(PureData.External/MethodAnything)", (const void *)PD_AddAnything); - - mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol,PureData.Symbol)", (const void *)PD_AddInlet); + mono_add_internal_call("PureData.External::PostVerbose(int,string)",(const void *)PD_PostVerbose); + + mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodBang)", (const void *)PD_AddMethodBang); + mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodFloat)", (const void *)PD_AddMethodFloat); + mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodSymbol)", (const void *)PD_AddMethodSymbol); + mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodPointer)", (const void *)PD_AddMethodPointer); + mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodList)", (const void *)PD_AddMethodList); + mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodAnything)", (const void *)PD_AddMethodSelector); + mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodAnything)", (const void *)PD_AddMethodAnything); + + mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol,PureData.Symbol)", (const void *)PD_AddInletAlias); mono_add_internal_call("PureData.Internal::AddInlet(void*,single&)", (const void *)PD_AddInletFloat); mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol&)", (const void *)PD_AddInletSymbol); // mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Pointer&)", (const void *)PD_AddInletPointer); +// mono_add_internal_call("PureData.Internal::AddInlet(void*,PureData.Symbol)", (const void *)PD_AddInletTyped); mono_add_internal_call("PureData.Internal::AddInlet(void*)", (const void *)PD_AddInletProxy); mono_add_internal_call("PureData.Internal::AddOutlet(void*,PureData.Symbol)", (const void *)PD_AddOutlet); @@ -759,17 +867,23 @@ void clr_setup(void) // static objects to avoid allocation at method call time clr_objarr_1 = mono_array_new(monodomain,mono_get_object_class(),1); - clr_objarr_2 = mono_array_new(monodomain,mono_get_object_class(),2); + clr_objarr_3 = mono_array_new(monodomain,mono_get_object_class(),3); + clr_obj_int = mono_object_new(monodomain,mono_get_int32_class()); clr_obj_single = mono_object_new(monodomain,mono_get_single_class()); clr_obj_symbol = mono_object_new(monodomain,clr_symbol); clr_obj_pointer = mono_object_new(monodomain,clr_pointer); clr_obj_atomlist = mono_object_new(monodomain,clr_atomlist); // unboxed addresses + clr_val_int = (int *)mono_object_unbox(clr_obj_int); clr_val_single = (float *)mono_object_unbox(clr_obj_single); clr_val_symbol = (t_symbol **)mono_object_unbox(clr_obj_symbol); clr_val_pointer = (void **)mono_object_unbox(clr_obj_pointer); clr_val_atomlist = (AtomList *)mono_object_unbox(clr_obj_atomlist); + // make proxy class + proxy_class = class_new(gensym("clr proxy"),NULL,NULL,sizeof(t_proxy),CLASS_PD|CLASS_NOINLET,A_NULL); + class_addanything(proxy_class,clr_method_proxy); + // install loader hook sys_loader(classloader); diff --git a/test-clr.pd b/test-clr.pd index 75721bc..653f984 100755 --- a/test-clr.pd +++ b/test-clr.pd @@ -1,4 +1,4 @@ -#N canvas 617 153 818 585 12; +#N canvas 617 153 842 609 12; #X floatatom 125 51 5 0 0 0 - - -; #X symbolatom 320 81 10 0 0 0 - - -; #X msg 536 45 msg one 2 three; @@ -23,7 +23,14 @@ #X obj 406 463 r receiver; #X obj 554 465 r receiver2; #X obj 555 499 print RECV2; -#X text 585 318 bang to see; +#X floatatom 526 362 5 0 0 0 - - -; +#X symbolatom 578 364 10 0 0 0 - - -; +#X text 585 318 passive - bang to see; +#X text 676 366 active; +#X msg 526 386 1 2 3; +#X floatatom 528 275 5 0 0 0 - - -; +#X msg 589 386 turalu; +#X msg 578 274 heyho; #X connect 0 0 3 0; #X connect 1 0 3 0; #X connect 2 0 3 0; @@ -44,3 +51,9 @@ #X connect 18 0 3 0; #X connect 20 0 19 0; #X connect 21 0 22 0; +#X connect 23 0 3 3; +#X connect 24 0 3 3; +#X connect 27 0 3 3; +#X connect 28 0 3 1; +#X connect 29 0 3 3; +#X connect 30 0 3 1; |