All pastes #2125967 Raw Edit

Someone

public cpp v1 · immutable
#2125967 ·published 2012-03-07 20:16 UTC
rendered paste body
Delegate^ SMBinder::BindToDelegate(SMScript^ script, Type^ delegateType, SMFunction^ func){	if (delegateType->IsAbstract)//can't instanciate abstract classes		return nullptr;	MethodInfo^ target = delegateType->GetMethod("Invoke");	MethodInfo^ wrapper = func->GetType()->GetMethod("Invoke", BindingFlags::Public | BindingFlags::Instance);	array<ParameterInfo^>^ params = target->GetParameters();	array<Type^>^ sigArgs = gcnew array<Type^>(params->Length + 1);	sigArgs[0] = array<Object^>::typeid;	for (int i = 1; i < sigArgs->Length; i++)		sigArgs[i] = params[i - 1]->ParameterType;	DynamicMethod^ method = gcnew DynamicMethod("SomeMethod", target->ReturnType, sigArgs, true);	ILGenerator^ methodIL = method->GetILGenerator();	LocalBuilder^ consts = methodIL->DeclareLocal(array<Object^>::typeid);    LocalBuilder^ args = methodIL->DeclareLocal(array<Object^>::typeid);	LocalBuilder^ instance = methodIL->DeclareLocal(SMFunction::typeid);    LocalBuilder^ returnType = methodIL->DeclareLocal(Type::typeid);    LocalBuilder^ returnValue = methodIL->DeclareLocal(Object::typeid);	methodIL->Emit(OpCodes::Ldarg_0);	methodIL->Emit(OpCodes::Stloc_S, consts);		//instance	methodIL->Emit(OpCodes::Ldloc_S, consts);    methodIL->Emit(OpCodes::Ldc_I4_S, 0);    methodIL->Emit(OpCodes::Ldelem_Ref);    methodIL->Emit(OpCodes::Castclass, SMFunction::typeid);	methodIL->Emit(OpCodes::Stloc_S, instance);    methodIL->Emit(OpCodes::Ldc_I4_S, sigArgs->Length - 1);    methodIL->Emit(OpCodes::Newarr, Object::typeid);    methodIL->Emit(OpCodes::Stloc_S, args);	for (int i = 1; i < sigArgs->Length; i++) {        methodIL->Emit(OpCodes::Ldloc_S, args);        methodIL->Emit(OpCodes::Ldc_I4_S, i - 1);        methodIL->Emit(OpCodes::Ldarg_S, i);        methodIL->Emit(OpCodes::Box, sigArgs[i]);        methodIL->Emit(OpCodes::Stelem_Ref);    }	methodIL->Emit(OpCodes::Ldloc_S, instance);    methodIL->Emit(OpCodes::Ldloc_S, args);    methodIL->Emit(OpCodes::Callvirt, wrapper);    methodIL->Emit(OpCodes::Stloc_S, returnValue);	//if the current delegate has a return type    //we want to convert the return value and unbox it    if (target->ReturnType != void::typeid) {		MethodInfo^ convert = (Interop::typeid)->GetMethod("ChangeType");		LocalBuilder^ scr = methodIL->DeclareLocal(SMScript::typeid);		//script		methodIL->Emit(OpCodes::Ldloc_S, consts);		methodIL->Emit(OpCodes::Ldc_I4_S, 1);		methodIL->Emit(OpCodes::Ldelem_Ref);		methodIL->Emit(OpCodes::Castclass, SMScript::typeid);		methodIL->Emit(OpCodes::Stloc_S, scr);		Label ELSE = methodIL->DefineLabel();        Label END =  methodIL->DefineLabel();         //load our return type metadata token		methodIL->Emit(OpCodes::Ldtoken, target->ReturnType);        methodIL->Emit(OpCodes::Call, Type::typeid->GetMethod("GetTypeFromHandle"));        methodIL->Emit(OpCodes::Stloc_S, returnType);		methodIL->Emit(OpCodes::Ldloc_S, scr);        methodIL->Emit(OpCodes::Ldloca_S, returnValue);        methodIL->Emit(OpCodes::Ldloc_S, returnType);        methodIL->Emit(OpCodes::Call, convert);        methodIL->Emit(OpCodes::Brfalse_S, ELSE);        methodIL->Emit(OpCodes::Br_S, END);        methodIL->MarkLabel(ELSE);		LocalBuilder^ local = methodIL->DeclareLocal(target->ReturnType);		methodIL->Emit(OpCodes::Ldloca, local);        methodIL->Emit(OpCodes::Initobj, local->LocalType);		methodIL->Emit(OpCodes::Ldloc_S, local);		methodIL->Emit(OpCodes::Box, Object::typeid);		methodIL->Emit(OpCodes::Stloc_S, returnValue);        methodIL->MarkLabel(END);        methodIL->Emit(OpCodes::Ldloc_S, returnValue);        methodIL->Emit(OpCodes::Unbox_Any, target->ReturnType);	}    methodIL->Emit(OpCodes::Ret);	return method->CreateDelegate(delegateType, gcnew array<Object^>{ func, script });}