public bool TryGetFunctionInfo(MethodInfo methodInfo, out CKlaxScriptFunctionInfo outFunctionInfo) { if (methodInfo == null) { outFunctionInfo = null; return(false); } return(m_klaxFunctionMap.TryGetValue(methodInfo, out outFunctionInfo)); }
public void GetNodeSuggestions(CKlaxScriptNodeQueryContext context, List <CKlaxScriptNodeFactory> suggestions) { if (suggestions.Capacity < MINIMUM_SUGGESTION_CAPACITY) { suggestions.Capacity = MINIMUM_SUGGESTION_CAPACITY; } suggestions.Clear(); for (int i = 0, count = Types.Count; i < count; i++) { CKlaxScriptTypeInfo type = Types[i]; bool bIncludeAll = type.Type == context.InputPinType; for (int k = 0, funcCount = type.Functions.Count; k < funcCount; k++) { CKlaxScriptFunctionInfo func = type.Functions[k]; Type declaringType = func.methodInfo.IsStatic ? null : func.methodInfo.DeclaringType; if (bIncludeAll || context.InputPinType == null || func.inputParameter.Any((t) => t.IsAssignableFrom(context.InputPinType))) { CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(func.displayName, func.category, func.tooltip, declaringType, false, () => { return(new CExecuteFunctionNode() { TargetMethod = func.methodInfo, IsImplicit = func.bIsImplicit, }); }); suggestions.Add(factory); } } int propertyCount = type.Properties.Count; for (int j = 0; j < propertyCount; j++) { CKlaxScriptPropertyInfo prop = type.Properties[j]; if (bIncludeAll || context.InputPinType == null || prop.propertyType.IsAssignableFrom(context.InputPinType) || prop.declaringType.IsAssignableFrom(context.InputPinType)) { CKlaxScriptNodeFactory getFactory = new CKlaxScriptNodeFactory("Get " + prop.displayName, prop.category, prop.tooltip, prop.declaringType, true, () => { return(prop.fieldInfo != null ? new CGetMemberNode(prop.fieldInfo) : new CGetMemberNode(prop.propertyInfo)); }); suggestions.Add(getFactory); if (!prop.bIsReadOnly) { CKlaxScriptNodeFactory setFactory = new CKlaxScriptNodeFactory("Set " + prop.displayName, prop.category, prop.tooltip, prop.declaringType, true, () => { return(prop.fieldInfo != null ? new CSetMemberNode(prop.fieldInfo) : new CSetMemberNode(prop.propertyInfo)); }); suggestions.Add(setFactory); } } } } for (int i = 0, funcCount = LibraryFunctions.Count; i < funcCount; i++) { CKlaxScriptFunctionInfo func = LibraryFunctions[i]; Type declaringType = func.methodInfo.IsStatic ? null : func.methodInfo.DeclaringType; if (context.InputPinType == null || func.inputParameter.Any((t) => t.IsAssignableFrom(context.InputPinType))) { CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(func.displayName, func.category, func.tooltip, declaringType, false, () => { return(new CExecuteFunctionNode() { TargetMethod = func.methodInfo, IsImplicit = func.bIsImplicit, }); }); suggestions.Add(factory); } } if (context.QueryObject != null) { foreach (CKlaxScriptInterfaceReference interfaceReference in context.QueryObject.IncludedInterfaces) { CKlaxScriptInterface klaxInterface = interfaceReference.GetInterface(); foreach (var interfaceFunction in klaxInterface.Functions) { CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(interfaceFunction.Name, "Interfaces", "", null, false, () => { return(new CExecuteInterfaceFunctionNode(interfaceFunction)); }); suggestions.Add(factory); } } foreach (CCustomFunctionGraph functionGraph in context.QueryObject.FunctionGraphs) { CKlaxScriptNodeFactory factory = new CKlaxScriptNodeFactory(functionGraph.Name, "Script Functions", "", null, false, () => { CExecuteCustomFunctionNode functionNode = new CExecuteCustomFunctionNode(functionGraph); functionNode.ResolveFunctionReference(context.QueryObject); return(functionNode); }); suggestions.Add(factory); } } suggestions.AddRange(m_customNodeFactories); }
private void GenerateMethod(CKlaxScriptFunctionInfo function, EKlaxFunctionLocation location, int typeIndex, int functionIndex) { MethodInfo methodInfo = function.methodInfo; ParameterInfo[] parameters = methodInfo.GetParameters(); ParameterInfo[] outParameters = parameters.Where(param => param.IsOut || (param.ParameterType.IsByRef && !param.IsIn)).ToArray(); ParameterInfo[] inRefParameters = parameters.Where(param => param.ParameterType.IsByRef && param.IsIn).ToArray(); ParameterInfo returnParameter = methodInfo.ReturnParameter; //Check if any invalid parameters are detected TypeBuilder typeBuilder = m_moduleBuilder.DefineType(methodInfo.DeclaringType + "_" + methodInfo.Name + "_Type", TypeAttributes.Public); //Build MethodInfo field to map generated type to method info FieldBuilder methodLocationFieldBuilder = typeBuilder.DefineField(METHOD_LOCATION_NAME, typeof(EKlaxFunctionLocation), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasDefault | FieldAttributes.Literal); methodLocationFieldBuilder.SetConstant(location); FieldBuilder typeIndexFieldBuilder = typeBuilder.DefineField(TYPE_INDEX_NAME, typeof(int), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasDefault | FieldAttributes.Literal); typeIndexFieldBuilder.SetConstant(typeIndex); FieldBuilder functionIndexFieldBuilder = typeBuilder.DefineField(FUNCTION_INDEX_NAME, typeof(int), FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.HasDefault | FieldAttributes.Literal); functionIndexFieldBuilder.SetConstant(functionIndex); //Build execution method MethodBuilder methodBuilder = typeBuilder.DefineMethod(METHOD_NAME, MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, CallingConventions.Standard, null, new Type[] { m_genericObjectListType, m_genericObjectListType }); ILGenerator generator = methodBuilder.GetILGenerator(); bool bHasReturnType = returnParameter.ParameterType != typeof(void); bool bIsStaticFunction = methodInfo.IsStatic; int returnParameterCount = 0; int outParameterCount = 0; int inRefParameterCount = 0; if (returnParameter.ParameterType != typeof(void)) { generator.DeclareLocal(returnParameter.ParameterType); returnParameterCount++; } foreach (var outParam in outParameters) { generator.DeclareLocal(outParam.ParameterType.IsByRef ? outParam.ParameterType.GetElementType() : outParam.ParameterType); outParameterCount = outParameters.Length; } foreach (var inParam in inRefParameters) { generator.DeclareLocal(inParam.ParameterType.GetElementType()); inRefParameterCount = inRefParameters.Length; } //Fill local variables for in ref parameters of desired function for (int i = 0, length = inRefParameters.Length; i < length; i++) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4_S, (sbyte)(Array.IndexOf(parameters, inRefParameters[i]) + (bIsStaticFunction ? 0 : 1))); generator.Emit(OpCodes.Callvirt, m_genericObjectListGetter); Type underlyingType = inRefParameters[i].ParameterType.GetElementType(); if (underlyingType.IsValueType) { generator.Emit(OpCodes.Unbox_Any, underlyingType); } generator.Emit(OpCodes.Stloc, (short)(returnParameterCount + outParameterCount + i)); } //If we call a member function, convert the first argument into the target type and put onto evaluation stack if (!bIsStaticFunction) { generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldc_I4_0); generator.Emit(OpCodes.Callvirt, m_genericObjectListGetter); generator.Emit(OpCodes.Castclass, methodInfo.DeclaringType); } for (int i = 0, length = parameters.Length; i < length; i++) { if (parameters[i].IsOut) { //Put out parameters onto evaluation stack generator.Emit(OpCodes.Ldloca_S, (byte)(Array.IndexOf(outParameters, parameters[i]) + (bHasReturnType ? 1 : 0))); } else if (parameters[i].IsIn && parameters[i].ParameterType.IsByRef) { generator.Emit(OpCodes.Ldloca_S, (byte)(Array.IndexOf(inRefParameters, parameters[i]) + returnParameterCount + outParameterCount)); } else { PutObjectOntoEvaluationStack_IL(generator, i - GetOutParametersBefore(i, parameters) + (bIsStaticFunction ? 0 : 1), parameters[i].ParameterType); } } generator.Emit(OpCodes.Call, methodInfo); if (returnParameter.ParameterType != typeof(void)) { //Store return value in output list generator.Emit(OpCodes.Stloc_0); generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldloc_0); AddObjectToObjectList_IL(generator, returnParameter.ParameterType); } if (outParameters.Length > 0) { for (int i = 0, length = outParameters.Length; i < length; i++) { generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldloc, (short)(i + (bHasReturnType ? 1 : 0))); AddObjectToObjectList_IL(generator, outParameters[i].ParameterType); } } generator.Emit(OpCodes.Ret); typeBuilder.CreateType(); }
private CKlaxScriptFunctionInfo CreateFunction(KlaxFunctionAttribute attribute, MethodInfo method) { ParameterInfo[] parameters = method.GetParameters(); CKlaxScriptFunctionInfo info = new CKlaxScriptFunctionInfo { methodInfo = method, displayName = attribute.DisplayName ?? method.Name, category = attribute.Category, tooltip = attribute.Tooltip, inputParameter = parameters.Where(whereInfo => !whereInfo.IsOut).Select(selectInfo => selectInfo.ParameterType).ToArray(), inputParametersDefaultValue = method.GetParameters().Where(whereInfo => !whereInfo.IsOut).Select(selectInfo => (selectInfo.HasDefaultValue ? selectInfo.DefaultValue : null)).ToArray(), bIsImplicit = attribute.IsImplicit, }; info.inputParameterNames = new string[info.inputParameter.Length]; for (int i = 0, length = info.inputParameter.Length; i < length; i++) { string result = parameters[i].Name; switch (i) { case 0: if (attribute.ParameterName1 != null) { result = attribute.ParameterName1; } break; case 1: if (attribute.ParameterName2 != null) { result = attribute.ParameterName2; } break; case 2: if (attribute.ParameterName3 != null) { result = attribute.ParameterName3; } break; case 3: if (attribute.ParameterName4 != null) { result = attribute.ParameterName4; } break; case 4: if (attribute.ParameterName5 != null) { result = attribute.ParameterName5; } break; case 5: if (attribute.ParameterName6 != null) { result = attribute.ParameterName6; } break; case 6: if (attribute.ParameterName7 != null) { result = attribute.ParameterName7; } break; case 7: if (attribute.ParameterName8 != null) { result = attribute.ParameterName8; } break; case 8: if (attribute.ParameterName9 != null) { result = attribute.ParameterName9; } break; case 9: if (attribute.ParameterName10 != null) { result = attribute.ParameterName10; } break; } info.inputParameterNames[i] = result; } m_klaxFunctionMap.Add(method, info); return(info); }
public SKlaxScriptFunctionProxy(CKlaxScriptFunctionInfo method) { methodInfo = method.methodInfo; compiledMethod = method.compiledMethod; bIsCompiled = compiledMethod != null; }