public DelegateCodeGen(CodeGenerator cg, DelegateBindingInfo delegateBindingInfo, int index) { this.cg = cg; var nargs = delegateBindingInfo.parameters.Length; var retName = this.cg.bindingManager.GetUniqueName(delegateBindingInfo.parameters, "ret"); var firstArgument = typeof(DuktapeDelegate) + " fn"; var returnTypeName = this.cg.bindingManager.GetCSTypeFullName(delegateBindingInfo.returnType); var delegateName = DuktapeVM._DuktapeDelegates + index; var arglist = this.cg.bindingManager.GetCSArglistDecl(delegateBindingInfo.parameters); foreach (var target in delegateBindingInfo.types) { this.cg.cs.AppendLine("[{0}(typeof({1}))]", this.cg.bindingManager.GetCSTypeFullName(typeof(JSDelegateAttribute)), this.cg.bindingManager.GetCSTypeFullName(target)); this.cg.bindingManager.log.AppendLine("emitting delegate decl: {0}", target); } if (!string.IsNullOrEmpty(arglist)) { arglist = ", " + arglist; } this.cg.cs.AppendLine($"public static {returnTypeName} {delegateName}({firstArgument}{arglist}) {{"); this.cg.cs.AddTabLevel(); this.cg.cs.AppendLine("var ctx = fn.ctx;"); this.cg.cs.AppendLine("if (ctx == IntPtr.Zero)"); this.cg.cs.AppendLine("{"); this.cg.cs.AddTabLevel(); this.cg.cs.AppendLine("throw new InvalidOperationException(\"duktape vm context has already been released.\");"); this.cg.cs.DecTabLevel(); this.cg.cs.AppendLine("}"); if (nargs > 0) { this.cg.cs.AppendLine("fn.BeginInvoke(ctx);"); for (var i = 0; i < nargs; i++) { var parameter = delegateBindingInfo.parameters[i]; this.cg.AppendPushValue(parameter.ParameterType, parameter.Name); } this.cg.cs.AppendLine("fn.EndInvoke(ctx);"); } else { this.cg.cs.AppendLine("fn.BeginInvoke(ctx);"); this.cg.cs.AppendLine("fn.EndInvoke(ctx);"); } if (delegateBindingInfo.returnType != typeof(void)) { this.cg.cs.AppendLine($"{this.cg.bindingManager.GetCSTypeFullName(delegateBindingInfo.returnType)} {retName};"); this.cg.cs.AppendLine(this.cg.bindingManager.GetDuktapeGetter(delegateBindingInfo.returnType, "ctx", "-1", retName)); this.cg.cs.AppendLine("DuktapeDLL.duk_pop(ctx);"); this.cg.cs.AppendLine($"return {retName};"); } else { this.cg.cs.AppendLine("DuktapeDLL.duk_pop(ctx);"); } }
public void OnPostGenerateDelegate(DelegateBindingInfo bindingInfo) { for (int i = 0, size = _bindingProcess.Count; i < size; i++) { var bp = _bindingProcess[i]; try { bp.OnPostGenerateDelegate(this, bindingInfo); } catch (Exception exception) { this.Error($"process failed [{bp}][OnPostGenerateDelegate]: {exception}"); } } }
// 收集所有 delegate 类型 public void CollectDelegate(Type type) { if (type == null || type.BaseType != typeof(MulticastDelegate)) { return; } if (!exportedDelegates.ContainsKey(type)) { var invoke = type.GetMethod("Invoke"); var returnType = invoke.ReturnType; var parameters = invoke.GetParameters(); if (ContainsPointer(invoke)) { log.AppendLine("skip unsafe (pointer) delegate: [{0}] {1}", type, invoke); return; } // 是否存在等价 delegate foreach (var kv in exportedDelegates) { if (kv.Value.Equals(returnType, parameters)) { log.AppendLine("skip delegate: {0} && {1}", kv.Value, type); kv.Value.types.Add(type); redirectDelegates[type] = kv.Key; return; } } var delegateBindingInfo = new DelegateBindingInfo(returnType, parameters); delegateBindingInfo.types.Add(type); exportedDelegates.Add(type, delegateBindingInfo); log.AppendLine("add delegate: {0}", type); for (var i = 0; i < parameters.Length; i++) { CollectDelegate(parameters[i].ParameterType); } } }
public void Generate() { var cg = new CodeGenerator(this); var outDir = prefs.outDir; var tx = prefs.extraExt; // var tx = ""; if (!Directory.Exists(outDir)) { Directory.CreateDirectory(outDir); } var cancel = false; var current = 0; var total = exportedTypes.Count; foreach (var typeKV in exportedTypes) { var typeBindingInfo = typeKV.Value; try { current++; cancel = EditorUtility.DisplayCancelableProgressBar( "Generating", $"{current}/{total}: {typeBindingInfo.FullName}", (float)current / total); if (cancel) { Warn("operation canceled"); break; } if (!typeBindingInfo.omit) { cg.Clear(); OnPreGenerateType(typeBindingInfo); cg.Generate(typeBindingInfo); OnPostGenerateType(typeBindingInfo); cg.WriteTo(outDir, typeBindingInfo.GetFileName(), tx); } } catch (Exception exception) { Error($"generate failed {typeBindingInfo.type.FullName}: {exception.Message}"); Debug.LogError(exception.StackTrace); } } if (!cancel) { try { var exportedDelegatesArray = new DelegateBindingInfo[this.exportedDelegates.Count]; this.exportedDelegates.Values.CopyTo(exportedDelegatesArray, 0); cg.Clear(); cg.Generate(exportedDelegatesArray); // cg.tsSource.enabled = false; cg.WriteTo(outDir, DuktapeVM._DuktapeDelegates, tx); } catch (Exception exception) { Error($"generate delegates failed: {exception.Message}"); Debug.LogError(exception.StackTrace); } } var logPath = prefs.logPath; File.WriteAllText(logPath, log.ToString()); EditorUtility.ClearProgressBar(); }
public virtual void OnPostGenerateDelegate(BindingManager bindingManager, DelegateBindingInfo bindingInfo) { }