X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fdotnet%2FInvoker.cpp;fp=rts%2Fdotnet%2FInvoker.cpp;h=d8ad87212df9ea96e6fcaec0ba9c46da4c931c29;hb=0065d5ab628975892cea1ec7303f968c3338cbe1;hp=0000000000000000000000000000000000000000;hpb=28a464a75e14cece5db40f2765a29348273ff2d2;p=ghc-hetmet.git diff --git a/rts/dotnet/Invoker.cpp b/rts/dotnet/Invoker.cpp new file mode 100644 index 0000000..d8ad872 --- /dev/null +++ b/rts/dotnet/Invoker.cpp @@ -0,0 +1,338 @@ +// +// (c) 2002-2003, sof. +// +// Dynamic invocation helper classes. The details of how +// to access the .NET object model via the Reflection API +// is taken care of by Invoker.{h,cpp} +// +#include "Invoker.h" + +namespace DynInvoke { + +static TypeName* ParseType(String* str) { + int curPos = 0; + int endPos; + + // Console::WriteLine("x{0}y", str); + TypeName* typeName = new TypeName(); + + if ( str->get_Chars(0) == '[' ) { + endPos = str->IndexOf(']'); + curPos = endPos + 1; + typeName->m_assembly = str->Substring(1,endPos-1); + typeName->m_length = endPos+1; + } + String* delimStr = " ,()"; + Char delims __gc [] = delimStr->ToCharArray(); + + endPos = str->IndexOfAny(delims,curPos); + // Console::WriteLine("{0} {1} x{2}x", __box(endPos), __box(curPos), str); + if ( endPos == -1 ) { + typeName->m_class = str->Substring(curPos); + } else { + typeName->m_class = str->Substring(curPos,endPos-curPos); + } + + // typeName->m_class = str->Substring(curPos,endPos-curPos); + typeName->m_length += endPos-curPos; + + return typeName; +} + +// Method: GetType(String* typeName); +// +// Purpose: Assembly-savvy version of Type::GetType() +// +Type* InvokeBridge::GetType(String* typeName) { + + try { + Type* t = Type::GetType(typeName); + if (t) return t; + } catch (Exception*) { + ; + } + + for (int i=0;i < InvokeBridge::m_assemblies->Count; i++) { + try { + String* stuff = String::Format("{0},{1}",typeName,InvokeBridge::m_assemblies->get_Item(i)->ToString()); + // Console::WriteLine(stuff); + Type* t = Type::GetType(stuff); + if (t) { + return t; + } + } catch (Exception*) { + continue; + } + } + return 0; +} + +// +// Method: CreateInstance(String* typeName, Object* []) +// +// Purpose: Assembly-savvy invocation of Activator::CreateInstance +Object* InvokeBridge::CreateInstance(TypeName* typeName, + Object* args[]) { + + Object* instance = 0; + Type* t = InvokeBridge::GetType(typeName->toStdString()); + + // Console::WriteLine("x{0} y{1}", typeName->toStdString(), t); + if (!t) { + try { + Assembly* localA = Assembly::LoadFrom(typeName->m_assembly); + t = localA->GetType(typeName->m_class); + } catch (Exception* e) { + ; + } + } + + if (!t) { + try { + AppDomain* currentDomain = AppDomain::CurrentDomain; + + // Assembly* stuff[] = currentDomain->GetAssemblies(); + // for (int i=0;i < stuff.Length; i++) { + // Console::WriteLine("x{0} y{1}", stuff[i]->ToString(), stuff[i]->FullName); + // } + // Console::WriteLine("x{0} y{1}", typeName->toStdString(), t); + Assembly* localA = Assembly::LoadWithPartialName("HugsAssembly"); + t = localA->GetType(typeName->m_class); + // Console::WriteLine("x{0} y{1}", typeName->toStdString(), t); + } catch (Exception*) { + ; + } + } + + if (t) { + try { + Object* o =Activator::CreateInstance(t,(Object* [])args); + return o; + } catch (Exception* e) { + Console::WriteLine("Failure: {0}", e); + return 0; + } + } +} + +// +// Method: CreateObject(String* objSpec, Object* args[]) +// +// Purpose: Given a fully qualified name of a class/type, try +// to create an instance of it. +// +Object* InvokeBridge::CreateObject(String* assemName, + String* objSpec, + Object* args[]) { + + Object* instance = 0; + + // Unravel the name of the class/type. + TypeName* typeName = ParseType(objSpec); + + if (assemName != 0 && assemName->Length > 0) { + typeName->m_assembly = assemName; + } + + // Try creating the instance.. + try { + instance = InvokeBridge::CreateInstance(typeName,(Object* [])args); + } catch (Exception* e) { + Console::WriteLine("Unable to create instance \"{0}\" {1}", objSpec, e); + throw(e); + } + if (!instance) { + Console::WriteLine("Unable to create instance \"{0}\"", objSpec); + } + return instance; +} + +// +// Method: InvokeMethod +// +// Purpose: Given a pointer to an already created object, look up +// one of its method. If found, invoke the method passing it +// 'args' as arguments. +// +Object* +InvokeBridge::InvokeMethod(Object* obj, + String* methName, + Object* args[]) { + // Get the methods from the type + MethodInfo* methods __gc[] = obj->GetType()->GetMethods(); + MethodInfo* mInfo; + + if (!methods) { + Console::WriteLine("InvokeMethod: No matching types found"); + return 0; + } + + System::Reflection::BindingFlags flgs + = (System::Reflection::BindingFlags) // why do I need to cast? + (System::Reflection::BindingFlags::Public | + System::Reflection::BindingFlags::NonPublic | + System::Reflection::BindingFlags::Instance | + System::Reflection::BindingFlags::Static | + System::Reflection::BindingFlags::InvokeMethod); + + /* Caller is assumed to catch any exceptions raised. */ + return obj->GetType()->InvokeMember(methName, + flgs, + 0, + obj, + (Object __gc* [])args); +} + +// +// Method: InvokeStaticMethod +// +// Purpose: Invoke a static method, given the fully qualified name +// of the method (and its arguments). If found, invoke the +// method passing it 'args' as arguments. +// +Object* InvokeBridge::InvokeStaticMethod(String* assemName, + String* typeAndMethName, + Object* args[]) { + + // Get the methods from the type + MethodInfo* methods __gc[]; + MethodInfo* mInfo; + + int lastDot = typeAndMethName->LastIndexOf('.'); + String* className = typeAndMethName->Substring(0,lastDot); + String* methName = typeAndMethName->Substring(lastDot+1); + + // Unravel the name of the class/type. + TypeName* typeName = ParseType(className); + Type* t; + + if (assemName != 0 && assemName->Length > 0) { + typeName->m_assembly = assemName; + } + + try { + t = InvokeBridge::GetType(typeName->toStdString()); + + if (!t) { + try { + Assembly* localA = Assembly::LoadFrom(typeName->m_assembly); + t = localA->GetType(typeName->m_class); + // Console::WriteLine("InvokeStaticMethod: Type {0} found", t); + } catch (Exception* e) { + ; + } + } + + if (t) { + methods = t->GetMethods(); + } else { + Console::WriteLine("InvokeStaticMethod: Type {0} not found", className); + return 0; + } + } catch (Exception *e) { + Console::WriteLine("InvokeStaticMethod: Type {0} not found", className); + throw(e); + } + + System::Reflection::BindingFlags flgs + = (System::Reflection::BindingFlags) // why do I need to cast? + (System::Reflection::BindingFlags::DeclaredOnly | + System::Reflection::BindingFlags::Public | + System::Reflection::BindingFlags::NonPublic | + System::Reflection::BindingFlags::Static | + System::Reflection::BindingFlags::InvokeMethod); + + return t->InvokeMember(methName, + flgs, + 0, + 0, + (Object __gc* [])args); +} + +// +// Method: GetField +// +// Purpose: Fetch the (boxed) value of named field of a given object. +// +Object* InvokeBridge::GetField(Object* obj, System::String* fieldName) { + + FieldInfo* fInfo = obj->GetType()->GetField(fieldName); + return fInfo->GetValue(obj); +} + +// +// Method: GetStaticField +// +// Purpose: Fetch the (boxed) value of named static field. +// +Object* InvokeBridge::GetStaticField(System::String* clsName, + System::String* fieldName) { + + Type* ty = InvokeBridge::GetType(clsName); + System::Reflection::BindingFlags static_field_flgs + = (System::Reflection::BindingFlags) + (System::Reflection::BindingFlags::Public | + System::Reflection::BindingFlags::NonPublic | + System::Reflection::BindingFlags::FlattenHierarchy | + System::Reflection::BindingFlags::Static); + + FieldInfo* fInfo = ty->GetField(fieldName, static_field_flgs); + return fInfo->GetValue(0); // according to doc, ok to pass any val here. +} + +// +// Method: SetField +// +// Purpose: Replace the (boxed) value of named field of a given object. +// +void InvokeBridge::SetField(Object* obj, System::String* fieldName, Object* val) { + + FieldInfo* fInfo = obj->GetType()->GetField(fieldName); + fInfo->SetValue(obj,val); + return; +} + +// +// Method: SetStaticField +// +// Purpose: Replace the (boxed) value of named static field. +// +void InvokeBridge::SetStaticField(System::String* clsName, + System::String* fieldName, + Object* val) { + + Type* ty = InvokeBridge::GetType(clsName); + System::Reflection::BindingFlags static_field_flgs + = (System::Reflection::BindingFlags) + (System::Reflection::BindingFlags::Public | + System::Reflection::BindingFlags::NonPublic | + System::Reflection::BindingFlags::FlattenHierarchy | + System::Reflection::BindingFlags::Static); + + FieldInfo* fInfo = ty->GetField(fieldName,static_field_flgs); + fInfo->SetValue(0,val); + return; +} + +Object* InvokeBridge::NewString(System::String* s) +{ + System::String* c = System::String::Copy(s); + return dynamic_cast(c); +} + +Array* InvokeBridge::NewArgArray(int sz) +{ + return Array::CreateInstance(__typeof(Object), sz); +} + +void InvokeBridge::SetArg(Object* arr[], Object* val, int idx) +{ + arr->SetValue(val,idx); +} + +Object* InvokeBridge::GetArg(Object* arr[], int idx) +{ + return arr->GetValue(idx); +} + +} /* namespace */