summaryrefslogtreecommitdiff
path: root/ghc/rts/dotnet/Invoker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ghc/rts/dotnet/Invoker.cpp')
-rw-r--r--ghc/rts/dotnet/Invoker.cpp338
1 files changed, 338 insertions, 0 deletions
diff --git a/ghc/rts/dotnet/Invoker.cpp b/ghc/rts/dotnet/Invoker.cpp
new file mode 100644
index 0000000000..d8ad87212d
--- /dev/null
+++ b/ghc/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<Object*>(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 */