Analyzer.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using dnlib.DotNet;
  2. using HybridCLR.Editor.ABI;
  3. using HybridCLR.Editor.Meta;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using UnityEngine;
  10. namespace HybridCLR.Editor.ReversePInvokeWrap
  11. {
  12. public class RawReversePInvokeMethodInfo
  13. {
  14. public MethodDef Method { get; set; }
  15. public CustomAttribute GenerationAttribute { get; set; }
  16. }
  17. public class ABIReversePInvokeMethodInfo
  18. {
  19. public MethodDesc Method { get; set; }
  20. public int Count { get; set; }
  21. }
  22. public class Analyzer
  23. {
  24. private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>();
  25. private readonly List<RawReversePInvokeMethodInfo> _reversePInvokeMethods = new List<RawReversePInvokeMethodInfo>();
  26. public Analyzer(AssemblyCache cache, List<string> assemblyNames)
  27. {
  28. foreach (var assemblyName in assemblyNames)
  29. {
  30. _rootModules.Add(cache.LoadModule(assemblyName));
  31. }
  32. }
  33. private void CollectReversePInvokeMethods()
  34. {
  35. foreach (var mod in _rootModules)
  36. {
  37. Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}");
  38. for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++)
  39. {
  40. var method = mod.ResolveMethod(rid);
  41. //Debug.Log($"method:{method}");
  42. if (!method.IsStatic || !method.HasCustomAttributes)
  43. {
  44. continue;
  45. }
  46. CustomAttribute wa = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Name == "MonoPInvokeCallbackAttribute");
  47. if (wa == null)
  48. {
  49. continue;
  50. }
  51. //foreach (var ca in method.CustomAttributes)
  52. //{
  53. // Debug.Log($"{ca.AttributeType.FullName} {ca.TypeFullName}");
  54. //}
  55. _reversePInvokeMethods.Add(new RawReversePInvokeMethodInfo()
  56. {
  57. Method = method,
  58. GenerationAttribute = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "HybridCLR.ReversePInvokeWrapperGenerationAttribute"),
  59. });
  60. }
  61. }
  62. }
  63. public List<ABIReversePInvokeMethodInfo> BuildABIMethods()
  64. {
  65. var methodsBySig = new Dictionary<string, ABIReversePInvokeMethodInfo>();
  66. var typeCreator = new TypeCreator();
  67. foreach(var method in _reversePInvokeMethods)
  68. {
  69. MethodDesc desc = new MethodDesc
  70. {
  71. MethodDef = method.Method,
  72. ReturnInfo = new ReturnInfo { Type = typeCreator.CreateTypeInfo(method.Method.ReturnType)},
  73. ParamInfos = method.Method.Parameters.Select(p => new ParamInfo { Type = typeCreator.CreateTypeInfo(p.Type)}).ToList(),
  74. };
  75. desc.Init();
  76. if (!methodsBySig.TryGetValue(desc.Sig, out var arm))
  77. {
  78. arm = new ABIReversePInvokeMethodInfo()
  79. {
  80. Method = desc,
  81. Count = 0,
  82. };
  83. methodsBySig.Add(desc.Sig, arm);
  84. }
  85. int preserveCount = method.GenerationAttribute != null ? (int)method.GenerationAttribute.ConstructorArguments[0].Value : 1;
  86. arm.Count += preserveCount;
  87. }
  88. var methods = methodsBySig.Values.ToList();
  89. methods.Sort((a, b) => String.CompareOrdinal(a.Method.Sig, b.Method.Sig));
  90. return methods;
  91. }
  92. public void Run()
  93. {
  94. CollectReversePInvokeMethods();
  95. }
  96. }
  97. }