From ed0031b621c6cf8824a9a3e588426907244aeb7e Mon Sep 17 00:00:00 2001 From: Thomas Grill Date: Tue, 18 Apr 2006 01:38:08 +0000 Subject: implemented class-based method management very fast native-to-managed transition most of the logic transferred to the CLR side svn path=/trunk/externals/clr/; revision=4931 --- clr.cpp | 927 +++++++++++++++++++++------------------------------------------- 1 file changed, 295 insertions(+), 632 deletions(-) (limited to 'clr.cpp') diff --git a/clr.cpp b/clr.cpp index 5f0a96b..cef43ff 100755 --- a/clr.cpp +++ b/clr.cpp @@ -7,6 +7,9 @@ extern "C" { #include #include #include + +// we need this one - it's in mono-devel +gpointer mono_delegate_to_ftnptr (MonoDelegate *delegate); } #ifdef _MSC_VER @@ -30,6 +33,8 @@ extern "C" { #include +#define CALL __stdcall + // main class library #define CORELIB "PureData" #define DLLEXT "dll" @@ -40,35 +45,42 @@ extern "C" { static t_symbol *sym_object; -// cached mono data -static MonoDomain *monodomain; -static MonoClass *clr_symbol,*clr_pointer,*clr_atom,*clr_atomlist,*clr_external; -static MonoMethodDesc *clr_desc_tostring,*clr_desc_ctor; -static MonoMethod *clr_meth_invoke; -static MonoProperty *clr_prop_method; +struct PassedData +{ + MonoObject object; + MonoObject *klass; + MonoObject *ext; + MonoObject *obj; +}; struct AtomList { - int argc; + AtomList(int c,t_atom *v): argc(c),argv(v) {} + + int argc; t_atom *argv; - - void Set(int c,t_atom *v) { argc = c,argv = v; } }; -// transforms a pointer (like MonoObject *) into a 3 element-list + +// cached mono data +static MonoDomain *monodomain; +static PassedData *clr_pass; + +// transforms a pointer (like MonoObject *) into a atom list +template struct ObjectAtom { // 64-bit safe... - enum { bitshift = 22,size = sizeof(void*)*8/bitshift+1 }; + enum { bitshift = 22,size = sizeof(T)*8/bitshift+1 }; t_atom msg[size]; ObjectAtom() {} - ObjectAtom(void *o) + ObjectAtom(T o) { - size_t ptr = (size_t)o; + long ptr = (long)o; for(int i = 0; i < size; ++i) { SETFLOAT(msg+i,(int)(ptr&((1<>= bitshift; @@ -83,139 +95,37 @@ struct ObjectAtom return true; } - static void *ptr(const t_atom *argv) + static T ptr(const t_atom *argv) { - size_t ret = 0; + long ret = 0; for(int i = size-1; i >= 0; --i) ret = (ret< static T ptr(const t_atom *argv) { return (T)ptr(argv); } - operator t_atom *() { return msg; } }; -// temporary workspace items - -static MonoArray *clr_objarr_1,*clr_objarr_2,*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 -{ - enum Kind { k_bang,k_float,k_symbol,k_pointer,k_list,k_anything,k_object }; - - 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); - assert(methodinfo); - virtmethod = mono_object_get_virtual_method(methodinfo,clr_meth_invoke); - assert(virtmethod); - kind = k; - } - - inline MonoObject *invoke(MonoObject *obj,void *arg) 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 invoke(obj,clr_objarr_1); - } - - inline MonoObject *operator()(MonoObject *obj) const - { - return invoke(obj,NULL); - } - - 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 invoke(obj,clr_objarr_3); - } - - inline MonoObject *operator()(MonoObject *obj,int inlet,MonoObject *clrobj) const - { - *clr_val_int = inlet; - mono_array_set(clr_objarr_2,void*,0,clr_obj_int); - mono_array_set(clr_objarr_2,void*,1,clrobj); - return invoke(obj,clr_objarr_2); - } -}; +enum Kind { k_bang, k_float, k_symbol, k_pointer, k_list, k_anything, k_object }; -typedef std::map ClrMethodMap; -typedef std::vector ClrMethods; // this is the class structure // holding the pd and mono class -// and our CLR method pointers struct t_clr_class { t_class *pd_class; - MonoClass *mono_class; - MonoMethod *mono_ctor; - MonoClassField *obj_field; // ptr field in PureData.External - t_symbol *name; - Delegate method_bang,method_float,method_symbol,method_pointer,method_list,method_anything,method_object; - ClrMethods *methods; // explicit method selectors + MonoObject *mono_class; }; static t_class *proxy_class; +struct t_instance; + struct t_proxy { t_object pd_obj; // myself - t_clr *parent; // parent object + t_instance *parent; // parent object int inlet; }; @@ -232,302 +142,144 @@ 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 +struct t_instance { t_object pd_obj; // myself - t_clr_class *clr_clss; // pointer to our class structure + t_clr_class *pd_class; MonoObject *mono_obj; // the mono class instance - OutletArr *outlets; + guint32 mono_handle; // the mono class instance + + OutletArr *outlets; ProxyList *proxies; }; - +typedef void (__stdcall NewClass)(t_clr_class *c,const t_symbol *sym); +typedef void (__stdcall NewInstance)(t_instance *p,AtomList l); +typedef void (__stdcall CallBang)(); +typedef void (__stdcall CallFloat)(float f); +typedef void (__stdcall CallSymbol)(const t_symbol *sym); +typedef void (__stdcall CallPointer)(const t_gpointer *ptr); +typedef void (__stdcall CallList)(AtomList l); +typedef void (__stdcall CallAnything)(int inlet,const t_symbol *sym,AtomList l); +typedef void (__stdcall CallObject)(int inlet); + +static NewClass *newclass = NULL; +static NewInstance *newinstance = NULL; +static CallBang *callbang = NULL; +static CallFloat *callfloat = NULL; +static CallSymbol *callsymbol = NULL; +static CallPointer *callpointer = NULL; +static CallList *calllist = NULL; +static CallAnything *callanything = NULL; +static CallObject *callobject = NULL; + +#if 0 // Print error message given by exception -static void error_exc(char *txt,char *cname,MonoObject *exc) +static void error_exc(char* txt,char* cname,MonoObject* exc) { - MonoMethod *m = mono_method_desc_search_in_class(clr_desc_tostring,mono_get_exception_class()); + MonoMethod* m = mono_method_desc_search_in_class(clr_desc_tostring,mono_get_exception_class()); assert(m); m = mono_object_get_virtual_method(exc,m); assert(m); - MonoString *str = (MonoString *)mono_runtime_invoke(m,exc,NULL,NULL); + MonoString* str = (MonoString*)mono_runtime_invoke(m,exc,NULL,NULL); assert(str); error("CLR class %s: %s",txt,cname); error(mono_string_to_utf8(str)); } +#endif + -static void clr_method_bang(t_clr *x) +static void clr_method_bang(t_instance *x) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_bang(x->mono_obj); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callbang); + clr_pass->ext = x->mono_obj; + callbang(); } -static void clr_method_float(t_clr *x,t_float f) +static void clr_method_float(t_instance *x,t_float f) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_float(x->mono_obj,f); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callfloat); + clr_pass->ext = x->mono_obj; + callfloat(f); } -static void clr_method_symbol(t_clr *x,t_symbol *s) +static void clr_method_symbol(t_instance *x,t_symbol *s) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_symbol(x->mono_obj,s); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callsymbol); + clr_pass->ext = x->mono_obj; + callsymbol(s); } -static void clr_method_pointer(t_clr *x,t_gpointer *p) +static void clr_method_pointer(t_instance *x,t_gpointer *p) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_pointer(x->mono_obj,p); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(callpointer); + clr_pass->ext = x->mono_obj; + callpointer(p); } -static void clr_method_list(t_clr *x,t_symbol *,int argc,t_atom *argv) +static void clr_method_list(t_instance *x,t_symbol *,int argc,t_atom *argv) { - assert(x && x->clr_clss); - MonoObject *exc = x->clr_clss->method_list(x->mono_obj,argc,argv); - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + assert(calllist); + clr_pass->ext = x->mono_obj; + calllist(AtomList(argc,argv)); } -static void call_anything(t_clr *x,int inlet,t_symbol *s,int argc,t_atom *argv) +static void call_anything(t_instance *x,int inlet,t_symbol *s,int argc,t_atom *argv) { - assert(x && x->clr_clss); - - 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; - } - } - } - } - - // no selectors: general method - d = &x->clr_clss->method_anything; - - found: - - // we must have found something.... - assert(d); - - MonoObject *exc; - switch(d->kind) { - case Delegate::k_bang: - exc = (*d)(x->mono_obj); - break; - case Delegate::k_float: - if((argc == 1 || (argc >= 1 && s == &s_list)) && argv[0].a_type == A_FLOAT) - exc = (*d)(x->mono_obj,argv[0].a_w.w_float); - else { - error("%s - %s handler: float argument expected",x->clr_clss->name->s_name,s->s_name); - return; - } - break; - case Delegate::k_symbol: - if((argc == 1 || (argc >= 1 && s == &s_list)) && argv[0].a_type == A_SYMBOL) - exc = (*d)(x->mono_obj,argv[0].a_w.w_symbol); - else { - error("%s - %s handler: symbol argument expected",x->clr_clss->name->s_name,s->s_name); - return; - } - break; - case Delegate::k_pointer: - if((argc == 1 || (argc >= 1 && s == &s_list)) && argv[0].a_type == A_POINTER) - exc = (*d)(x->mono_obj,argv[0].a_w.w_gpointer); - else { - error("%s - %s handler: pointer argument expected",x->clr_clss->name->s_name,s->s_name); - return; - } - 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; - case Delegate::k_object: - if(s != sym_object || !ObjectAtom::check(argc,argv)) { - error("CLR - object handler: invalid arguments"); - return; - } - exc = (*d)(x->mono_obj,inlet,ObjectAtom::ptr(argv)); - break; - default: - assert(false); - } - - if(exc) error_exc("Exception raised",x->clr_clss->name->s_name,exc); + assert(x); + clr_pass->ext = x->mono_obj; + if(s == sym_object && ObjectAtom::check(argc,argv)) { + assert(callobject); + guint32 hnd = ObjectAtom::ptr(argv); + clr_pass->obj = mono_gchandle_get_target(hnd); + callobject(inlet); + } + else { + assert(callanything); + callanything(inlet,s,AtomList(argc,argv)); + } } -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_anything(t_instance *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) +static void CALL PD_Post(MonoString *str) { post("%s",mono_string_to_utf8(str)); } -static void PD_PostError(MonoString *str) +static void CALL PD_PostError(MonoString *str) { error("%s",mono_string_to_utf8(str)); } -static void PD_PostVerbose(int lvl,MonoString *str) +static void CALL PD_PostVerbose(int lvl,MonoString *str) { verbose(lvl,"%s",mono_string_to_utf8(str)); } -static void *PD_SymGen(MonoString *str) +static void *CALL PD_SymGen(MonoString *str) { assert(str); return gensym(mono_string_to_utf8(str)); } -static MonoString *PD_SymEval(t_symbol *sym) +static MonoString *CALL PD_SymEval(t_symbol *sym) { assert(sym); return mono_string_new(monodomain,sym->s_name); } -static void PD_AddMethodHandler(int inlet,t_symbol *sym,MonoObject *method,Delegate::Kind kind) -{ - 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); - 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_AddMethodBang(int inlet,MonoObject *method) -{ - 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_AddMethodFloat(int inlet,MonoObject *method) -{ - 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_AddMethodSymbol(int inlet,MonoObject *method) -{ - 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_AddMethodPointer(int inlet,MonoObject *method) -{ - 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); - } -} - -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_AddMethodAnything(int inlet,MonoObject *method) -{ - 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_AddMethodSelBang(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_bang); -} - -static void PD_AddMethodSelFloat(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_float); -} - -static void PD_AddMethodSelSymbol(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_symbol); -} -static void PD_AddMethodSelPointer(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_pointer); -} - -static void PD_AddMethodSelList(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_list); -} - -static void PD_AddMethodSelAnything(int inlet,t_symbol *sym,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym,method,Delegate::k_anything); -} - -static void PD_AddMethodObject(int inlet,MonoObject *method) -{ - PD_AddMethodHandler(inlet,sym_object,method,Delegate::k_object); -} - - -static void PD_AddInletAlias(t_clr *obj,t_symbol *sel,t_symbol *to_sel) +static void CALL PD_AddInletAlias(t_instance *obj,t_symbol *sel,t_symbol *to_sel) { ++clr_inlet; assert(obj); @@ -535,7 +287,7 @@ static void PD_AddInletAlias(t_clr *obj,t_symbol *sel,t_symbol *to_sel) assert(in); } -static void PD_AddInletFloat(t_clr *obj,float *f) +static void CALL PD_AddInletFloat(t_instance *obj,float *f) { ++clr_inlet; assert(obj); @@ -543,7 +295,7 @@ static void PD_AddInletFloat(t_clr *obj,float *f) assert(in); } -static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) +static void CALL PD_AddInletSymbol(t_instance *obj,t_symbol **s) { ++clr_inlet; assert(obj); @@ -552,7 +304,7 @@ static void PD_AddInletSymbol(t_clr *obj,t_symbol **s) } /* -static void PD_AddInletPointer(t_clr *obj,t_gpointer *p) +static void CALL PD_AddInletPointer(t_clr *obj,t_gpointer *p) { ++clr_inlet; assert(obj); @@ -561,7 +313,7 @@ static void PD_AddInletPointer(t_clr *obj,t_gpointer *p) } */ -static void PD_AddInletProxyTyped(t_clr *obj,t_symbol *type) +static void CALL PD_AddInletProxyTyped(t_instance *obj,t_symbol *type) { assert(obj); t_proxy *p = (t_proxy *)pd_new(proxy_class); @@ -573,10 +325,10 @@ static void PD_AddInletProxyTyped(t_clr *obj,t_symbol *type) assert(in); } -static void PD_AddInletProxy(t_clr *obj) { PD_AddInletProxyTyped(obj,NULL); } +static void CALL PD_AddInletProxy(t_instance *obj) { PD_AddInletProxyTyped(obj,NULL); } -static void PD_AddOutlet(t_clr *obj,t_symbol *type) +static void CALL PD_AddOutlet(t_instance *obj,t_symbol *type) { assert(obj); t_outlet *out = outlet_new(&obj->pd_obj,type); @@ -585,7 +337,7 @@ static void PD_AddOutlet(t_clr *obj,t_symbol *type) obj->outlets->push_back(out); } -static void PD_OutletBang(t_clr *obj,int n) +static void CALL PD_OutletBang(t_instance *obj,int n) { assert(obj); assert(obj->outlets); @@ -593,7 +345,7 @@ static void PD_OutletBang(t_clr *obj,int n) outlet_bang((*obj->outlets)[n]); } -static void PD_OutletFloat(t_clr *obj,int n,float f) +static void CALL PD_OutletFloat(t_instance *obj,int n,float f) { assert(obj); assert(obj->outlets); @@ -601,7 +353,7 @@ static void PD_OutletFloat(t_clr *obj,int n,float f) outlet_float((*obj->outlets)[n],f); } -static void PD_OutletSymbol(t_clr *obj,int n,t_symbol *s) +static void CALL PD_OutletSymbol(t_instance *obj,int n,t_symbol *s) { assert(obj); assert(obj->outlets); @@ -609,7 +361,7 @@ static void PD_OutletSymbol(t_clr *obj,int n,t_symbol *s) outlet_symbol((*obj->outlets)[n],s); } -static void PD_OutletPointer(t_clr *obj,int n,t_gpointer *p) +static void CALL PD_OutletPointer(t_instance *obj,int n,t_gpointer *p) { assert(obj); assert(obj->outlets); @@ -617,12 +369,12 @@ static void PD_OutletPointer(t_clr *obj,int n,t_gpointer *p) outlet_pointer((*obj->outlets)[n],p); } -static void PD_OutletAtom(t_clr *obj,int n,t_atom l) +static void CALL PD_OutletAtom(t_instance *obj,int n,t_atom l) { assert(obj); assert(obj->outlets); assert(n >= 0 && n < (int)obj->outlets->size()); - t_outlet *out = (*obj->outlets)[n]; + t_outlet* out = (*obj->outlets)[n]; switch(l.a_type) { case A_FLOAT: outlet_float(out,l.a_w.w_float); break; case A_SYMBOL: outlet_symbol(out,l.a_w.w_symbol); break; @@ -631,15 +383,7 @@ static void PD_OutletAtom(t_clr *obj,int n,t_atom l) } } -static void PD_OutletAnything(t_clr *obj,int n,t_symbol *s,AtomList l) -{ - assert(obj); - assert(obj->outlets); - assert(n >= 0 && n < (int)obj->outlets->size()); - outlet_anything((*obj->outlets)[n],s,l.argc,l.argv); -} - -static void PD_OutletAnything2(t_clr *obj,int n,t_symbol *s,MonoArray *l) +static void CALL PD_OutletAnything(t_instance *obj,int n,t_symbol *s,MonoArray *l) { assert(obj); assert(obj->outlets); @@ -649,50 +393,68 @@ static void PD_OutletAnything2(t_clr *obj,int n,t_symbol *s,MonoArray *l) } -static void PD_OutletObject(t_clr *obj,int n,MonoObject *o) +static void CALL PD_OutletObject(t_instance *obj,int n,MonoObject *o) { assert(obj); assert(obj->outlets); assert(n >= 0 && n < (int)obj->outlets->size()); - ObjectAtom oa(o); + guint32 hnd = mono_gchandle_new(o,TRUE); + ObjectAtom oa(hnd); outlet_anything((*obj->outlets)[n],sym_object,oa.size,oa); + mono_gchandle_free(hnd); } -static void PD_SendAtom(t_symbol *dst,t_atom a) +static void CALL PD_SendAtom(t_symbol *dst,t_atom a) { void *cl = dst->s_thing; if(cl) pd_forwardmess((t_class **)cl,1,&a); } -static void PD_SendAnything(t_symbol *dst,t_symbol *s,AtomList l) -{ - void *cl = dst->s_thing; - if(cl) pd_typedmess((t_class **)cl,s,l.argc,l.argv); -} - -static void PD_SendAnything2(t_symbol *dst,t_symbol *s,MonoArray *l) +static void CALL PD_SendAnything(t_symbol *dst,t_symbol *s,MonoArray *l) { void *cl = dst->s_thing; // assert(mono_object_get_class(&l->obj) == clr_atom); if(cl) pd_typedmess((t_class **)cl,s,mono_array_length(l),mono_array_addr(l,t_atom,0)); } -static void PD_SendObject(t_symbol *dst,MonoObject *o) +static void CALL PD_SendObject(t_symbol *dst,MonoObject *o) { void *cl = dst->s_thing; // assert(mono_object_get_class(&l->obj) == clr_atom); if(cl) { - ObjectAtom oa(o); + guint32 hnd = mono_gchandle_new(o,TRUE); + ObjectAtom oa(hnd); pd_typedmess((t_class **)cl,sym_object,oa.size,oa); + mono_gchandle_free(hnd); } } +static MonoString *CALL PD_SearchPath(MonoString *file) +{ + char *filestr = mono_string_to_utf8(file); + char dirbuf[MAXPDSTRING],*nameptr; + // search for classname.dll in the PD path + int fd; + if ((fd = open_via_path("",filestr,"",dirbuf, &nameptr, MAXPDSTRING, 1)) >= 0) { + // found + if(dirbuf != nameptr) { + // fix for the fact that open_via_path doesn't return a path, when it's found in . + strcat(dirbuf,"/"); + strcat(dirbuf,filestr); + +// close(fd); // strange - we get an assertion failure here... + } + return mono_string_new(monodomain,dirbuf); + } + else + return mono_string_new(monodomain,""); +} + void *clr_new(t_symbol *classname, int argc, t_atom *argv) { - // find class name in map - + // 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); @@ -702,51 +464,37 @@ void *clr_new(t_symbol *classname, int argc, t_atom *argv) 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; - x->clr_clss->name = classname; - - // store our object pointer in External::ptr member - mono_field_set_value(x->mono_obj,clss->obj_field,x); - + t_instance *x = (t_instance *)pd_new(clss->pd_class); + x->pd_class = clss; x->outlets = NULL; x->proxies = NULL; - // ok, we have an object - look for constructor - if(clss->mono_ctor) { - // reset inlet index - clr_inlet = 0; + clr_inlet = 0; - AtomList al; - al.Set(argc,argv); - gpointer args = &al; + assert(newinstance); - // call constructor - MonoObject *exc; - mono_runtime_invoke(clss->mono_ctor,x->mono_obj,&args,&exc); - - if(exc) { - pd_free((t_pd *)x); - error_exc("exception raised in constructor",classname->s_name,exc); - return NULL; - } - } - else - verbose(1,"CLR - Warning: no constructor for class %s found",classname->s_name); + clr_pass->klass = clss->mono_class; + newinstance(x,AtomList(argc,argv)); + x->mono_obj = clr_pass->ext; +#ifdef _DEBUG + clr_pass->klass = NULL; +#endif - return x; + if(x->mono_obj) { + x->mono_handle = mono_gchandle_new(x->mono_obj,TRUE); + return x; + } + else { + pd_free((t_pd *)x); + error("CLR - class %s could not be instantiated",classname->s_name); + return NULL; + } } -void clr_free(t_clr *obj) +void clr_free(t_instance *obj) { + mono_gchandle_free(obj->mono_handle); + if(obj->outlets) delete obj->outlets; if(obj->proxies) { @@ -755,129 +503,67 @@ void clr_free(t_clr *obj) } } -static int classloader(char *dirname, char *classname, char *altname) +static void CALL PD_Register(MonoDelegate *d_class,MonoDelegate *d_new,MonoDelegate *d_bang,MonoDelegate *d_float,MonoDelegate *d_symbol,MonoDelegate *d_pointer,MonoDelegate *d_list,MonoDelegate *d_anything,MonoDelegate *d_object) { - t_clr_class *clr_class = NULL; - t_symbol *classsym; - MonoAssembly *assembly; - MonoImage *image; - MonoMethod *method; - int flags = CLASS_DEFAULT; - - char *realname; - char dirbuf[MAXPDSTRING],*nameptr; - // search for classname.dll in the PD path - int fd; - if ((fd = open_via_path(dirname, realname = classname, "." DLLEXT, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) - if (!altname || (fd = open_via_path(dirname, realname = altname, "." DLLEXT, dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) - // not found - goto bailout; - - // found - close(fd); - - clr_class = (t_clr_class *)getbytes(sizeof(t_clr_class)); - // set all struct members to 0 - memset(clr_class,0,sizeof(*clr_class)); - - // try to load assembly - strcat(dirbuf,"/"); - strcat(dirbuf,realname); - strcat(dirbuf,"." DLLEXT); + newclass = (NewClass *)mono_delegate_to_ftnptr(d_class); + newinstance = (NewInstance *)mono_delegate_to_ftnptr(d_new); + callbang = (CallBang *)mono_delegate_to_ftnptr(d_bang); + callfloat = (CallFloat *)mono_delegate_to_ftnptr(d_float); + callsymbol = (CallSymbol *)mono_delegate_to_ftnptr(d_symbol); + callpointer = (CallPointer *)mono_delegate_to_ftnptr(d_pointer); + calllist = (CallList *)mono_delegate_to_ftnptr(d_list); + callanything = (CallAnything *)mono_delegate_to_ftnptr(d_anything); + callobject = (CallObject *)mono_delegate_to_ftnptr(d_object); +} - assembly = mono_domain_assembly_open(monodomain,dirbuf); - if(!assembly) { - error("clr: file %s couldn't be loaded!",dirbuf); - goto bailout; +static bool CALL PD_RegisterClass(t_clr_class *c,t_symbol *classsym,int classflags,int methodflags) +{ + assert(c && !c->pd_class); + c->pd_class = class_new(classsym,(t_newmethod)clr_new,(t_method)clr_free, sizeof(t_instance), classflags, A_GIMME, A_NULL); + if(c->pd_class) { + if(methodflags&0x01) class_addbang(c->pd_class,clr_method_bang); + if(methodflags&0x02) class_addfloat(c->pd_class,clr_method_float); + if(methodflags&0x04) class_addsymbol(c->pd_class,clr_method_symbol); + if(methodflags&0x08) class_addpointer(c->pd_class,clr_method_pointer); + if(methodflags&0x10) class_addlist(c->pd_class,clr_method_list); + if(methodflags&0x20) class_addanything(c->pd_class,clr_method_anything); + return true; } + else + return false; +} - image = mono_assembly_get_image(assembly); - assert(image); - // try to find class - // "" means no namespace - clr_class->mono_class = mono_class_from_name(image,"",realname); - if(!clr_class->mono_class) { - error("Can't find %s class in %s\n",classname,mono_image_get_filename(image)); - goto bailout; +static int classloader(char *dirname, char *classname, char *altname) +{ + if(!newclass) { + post("CLR - Entry point not set"); + return 0; } - // make new class (with classname) - classsym = gensym(classname); - clr_class->pd_class = NULL; - - clr_class->obj_field = mono_class_get_field_from_name(clr_class->mono_class,"ptr"); - assert(clr_class->obj_field); - - // find static Setup method - MonoMethodDesc *clr_desc_main = mono_method_desc_new("::Setup",FALSE); - assert(clr_desc_main); + t_symbol *classsym = gensym(classname); - method = mono_method_desc_search_in_class(clr_desc_main,clr_class->mono_class); - if(method) { - MonoObject *obj = mono_object_new(monodomain,clr_class->mono_class); - if(!obj) { - error("CLR class %s could not be instantiated",classname); - goto bailout; - } - - // store NULL in External::ptr member - mono_field_set_value(obj,clr_class->obj_field,NULL); - - // set current class - clr_setup_class = clr_class; + t_clr_class *classdef = (t_clr_class *)getbytes(sizeof(t_clr_class)); + // set all struct members to 0 + memset(classdef,0,sizeof(t_clr_class)); - // call static Setup method - gpointer args = obj; - MonoObject *exc; - MonoObject *ret = mono_runtime_invoke(method,NULL,&args,&exc); - if(ret) { - // \TODO check return type - flags = *(int *)mono_object_unbox(ret); - } + newclass(classdef,classsym); + classdef->mono_class = clr_pass->klass; - // unset current class - clr_setup_class = NULL; + if(!classdef->mono_class) + { + freebytes(classdef,sizeof(t_clr_class)); + return 0; + } - if(exc) { - error_exc("CLR - Exception raised by Setup",classname,exc); - goto bailout; - } - } - else - post("CLR - Warning: no %s.Setup method found",classname); - - // find and save constructor - clr_class->mono_ctor = mono_method_desc_search_in_class(clr_desc_ctor,clr_class->mono_class); - - // 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); - - // register methods - if(clr_class->method_bang) - class_addbang(clr_class->pd_class,clr_method_bang); - if(clr_class->method_float) - class_addfloat(clr_class->pd_class,clr_method_float); - if(clr_class->method_symbol) - class_addsymbol(clr_class->pd_class,clr_method_symbol); - if(clr_class->method_pointer) - class_addpointer(clr_class->pd_class,clr_method_pointer); - if(clr_class->method_list) - class_addlist(clr_class->pd_class,clr_method_list); - if(clr_class->method_anything || clr_class->methods) - class_addanything(clr_class->pd_class,clr_method_anything); + mono_gchandle_new(classdef->mono_class,TRUE); // we don't remember the handle... won't be freed later // put into map - clr_map[classsym] = clr_class; + clr_map[classsym] = classdef; verbose(1,"CLR - Loaded class %s OK",classname); return 1; - -bailout: - if(clr_class) freebytes(clr_class,sizeof(t_clr_class)); - - return 0; } extern "C" @@ -902,26 +588,29 @@ void clr_setup(void) mono_set_dirs(tlib,tconf); #endif + // try to find PureData.dll in the PD path + char dirbuf[MAXPDSTRING],*nameptr; + // search in the PD path + int fd; + if ((fd = open_via_path("",CORELIB,"." DLLEXT,dirbuf,&nameptr,MAXPDSTRING,1)) >= 0) { + if(dirbuf != nameptr) // fix for the fact that open_via_path doesn't return a path, when it's found in . + strcat(dirbuf,"/" CORELIB "." DLLEXT); +// close(fd); // strange - we get an assertion failure here... + } + else { + error("CLR - " CORELIB "." DLLEXT " not found in path"); + return; + } + try { - monodomain = mono_jit_init(CORELIB); + monodomain = mono_jit_init(dirbuf); } catch(...) { monodomain = NULL; } - if(monodomain) { - // try to find PureData.dll in the PD path - char dirbuf[MAXPDSTRING],*nameptr; - // search in the PD path - int fd; - if ((fd = open_via_path("",CORELIB,"." DLLEXT,dirbuf,&nameptr,MAXPDSTRING,1)) >= 0) { - if(dirbuf != nameptr) // fix for the fact that open_via_path doesn't return a path, when it's found in . - strcat(dirbuf,"/" CORELIB "." DLLEXT); - close(fd); - } - else - strcpy(dirbuf,CORELIB "." DLLEXT); + if(monodomain) { // look for PureData.dll MonoAssembly *assembly = mono_domain_assembly_open (monodomain,dirbuf); if(!assembly) { @@ -935,92 +624,43 @@ void clr_setup(void) // add mono to C hooks mono_add_internal_call("PureData.Internal::SymGen(string)", (const void *)PD_SymGen); - mono_add_internal_call("PureData.Internal::SymEval(void*)", (const void *)PD_SymEval); - - 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::PostVerbose(int,string)",(const void *)PD_PostVerbose); - - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/Method)", (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.External/MethodAnything)", (const void *)PD_AddMethodAnything); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/Method)", (const void *)PD_AddMethodSelBang); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodFloat)", (const void *)PD_AddMethodSelFloat); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodSymbol)", (const void *)PD_AddMethodSelSymbol); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodPointer)", (const void *)PD_AddMethodSelPointer); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodList)", (const void *)PD_AddMethodSelList); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.Symbol,PureData.External/MethodAnything)", (const void *)PD_AddMethodSelAnything); - mono_add_internal_call("PureData.External::AddMethod(int,PureData.External/MethodObject)", (const void *)PD_AddMethodObject); - - 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); - - mono_add_internal_call("PureData.Internal::Outlet(void*,int)", (const void *)PD_OutletBang); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,single)", (const void *)PD_OutletFloat); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol)", (const void *)PD_OutletSymbol); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Pointer)", (const void *)PD_OutletPointer); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Atom)", (const void *)PD_OutletAtom); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol,PureData.AtomList)", (const void *)PD_OutletAnything); - mono_add_internal_call("PureData.Internal::Outlet(void*,int,PureData.Symbol,PureData.Atom[])", (const void *)PD_OutletAnything2); - mono_add_internal_call("PureData.Internal::OutletEx(void*,int,object)", (const void *)PD_OutletObject); - -// mono_add_internal_call("PureData.Internal::Bind(void*,PureData.Symbol)", (const void *)PD_Bind); -// mono_add_internal_call("PureData.Internal::Unbind(void*,PureData.Symbol)", (const void *)PD_Unbind); + mono_add_internal_call("PureData.Internal::SymEval(PureData.Symbol)", (const void *)PD_SymEval); + + mono_add_internal_call("PureData.Public::Post(string)",(const void *)PD_Post); + mono_add_internal_call("PureData.Public::PostError(string)",(const void *)PD_PostError); + mono_add_internal_call("PureData.Public::PostVerbose(int,string)",(const void *)PD_PostVerbose); + mono_add_internal_call("PureData.Public::SearchPath(string)",(const void *)PD_SearchPath); + + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Symbol,PureData.Symbol)", (const void *)PD_AddInletAlias); + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,single&)", (const void *)PD_AddInletFloat); + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Symbol&)", (const void *)PD_AddInletSymbol); +// mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Pointer&)", (const void *)PD_AddInletPointer); +// mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_AddInletTyped); + mono_add_internal_call("PureData.Internal::AddInlet(PureData.ExternalPtr)", (const void *)PD_AddInletProxy); + + mono_add_internal_call("PureData.Internal::AddOutlet(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_AddOutlet); + + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int)", (const void *)PD_OutletBang); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,single)", (const void *)PD_OutletFloat); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Symbol)", (const void *)PD_OutletSymbol); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Pointer)", (const void *)PD_OutletPointer); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Atom)", (const void *)PD_OutletAtom); + mono_add_internal_call("PureData.Internal::Outlet(PureData.ExternalPtr,int,PureData.Symbol,PureData.Atom[])", (const void *)PD_OutletAnything); + mono_add_internal_call("PureData.Internal::OutletEx(PureData.ExternalPtr,int,object)", (const void *)PD_OutletObject); + +// mono_add_internal_call("PureData.Internal::Bind(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_Bind); +// mono_add_internal_call("PureData.Internal::Unbind(PureData.ExternalPtr,PureData.Symbol)", (const void *)PD_Unbind); + + mono_add_internal_call("PureData.Class::Register(PureData.Class/DelegateClass,PureData.Class/DelegateNew,PureData.Class/DelegateBang,PureData.Class/DelegateFloat,PureData.Class/DelegateSymbol,PureData.Class/DelegatePointer,PureData.Class/DelegateList,PureData.Class/DelegateAnything,PureData.Class/DelegateObject)", (const void *)PD_Register); + mono_add_internal_call("PureData.Class::RegisterClass(PureData.ClassPtr,PureData.Symbol,PureData.Public/ClassType,PureData.Class/MethodFlags)", (const void *)PD_RegisterClass); +// mono_add_internal_call("PureData.Class::AddMethodIntern(PureData.ClassPtr,int,PureData.Symbol,PureData.Class/Kind,System.Delegate)", (const void *)PD_AddMethodIntern); mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Atom)", (const void *)PD_SendAtom); - mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.AtomList)", (const void *)PD_SendAnything); - mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.Atom[])", (const void *)PD_SendAnything2); + mono_add_internal_call("PureData.External::Send(PureData.Symbol,PureData.Symbol,PureData.Atom[])", (const void *)PD_SendAnything); mono_add_internal_call("PureData.External::SendEx(PureData.Symbol,object)", (const void *)PD_SendObject); - // load important classes - clr_symbol = mono_class_from_name(image,"PureData","Symbol"); - assert(clr_symbol); - clr_pointer = mono_class_from_name(image,"PureData","Pointer"); - assert(clr_pointer); - clr_atom = mono_class_from_name(image,"PureData","Atom"); - assert(clr_atom); - clr_atomlist = mono_class_from_name(image,"PureData","AtomList"); - assert(clr_atomlist); - clr_external = mono_class_from_name(image,"PureData","External"); - assert(clr_external); - - clr_desc_tostring = mono_method_desc_new("::ToString()",FALSE); - assert(clr_desc_tostring); - clr_desc_ctor = mono_method_desc_new("::.ctor(AtomList)",FALSE); - assert(clr_desc_ctor); - - MonoMethodDesc *desc = mono_method_desc_new("System.Reflection.MethodBase:Invoke(object,object[])",FALSE); - clr_meth_invoke = mono_method_desc_search_in_image(desc,mono_get_corlib()); - - MonoClass *delegate = mono_class_from_name(mono_get_corlib(),"System","Delegate"); - assert(delegate); - clr_prop_method = mono_class_get_property_from_name(delegate,"Method"); - assert(clr_prop_method); - - // 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); @@ -1032,8 +672,31 @@ void clr_setup(void) // install loader hook sys_register_loader(classloader); - // ready! - post("CLR extension - (c)2006 Davide Morelli, Thomas Grill"); + /////////////////////////////////////////////////////////// + + // call static Class::Setup function + MonoClass *clr_class = mono_class_from_name(image,"PureData","Class"); + assert(clr_class); + MonoMethodDesc *desc = mono_method_desc_new("::Setup()",FALSE); + MonoMethod *setup = mono_method_desc_search_in_class(desc,clr_class); + + MonoObject *exc; + mono_runtime_invoke(setup,NULL,NULL,&exc); + if(exc) + post("CLR - setup function failed"); + else { + // ready! + post("CLR extension - (c)2006 Davide Morelli, Thomas Grill"); + } + + // necessary data should have been set by Setup + MonoClass *clr_internal = mono_class_from_name(image,"PureData","Internal"); + assert(clr_internal); + MonoVTable *clr_internal_vt = mono_class_vtable(monodomain,clr_internal); + MonoClassField *fld = mono_class_get_field_from_name (clr_internal,"pass"); + assert(fld); + mono_field_static_get_value(clr_internal_vt,fld,&clr_pass); + assert(clr_pass); } else error("clr: mono domain couldn't be initialized!"); -- cgit v1.2.1