Program.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. using System;
  2. using System.IO;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Runtime.InteropServices;
  6. using Urho;
  7. using Type = System.Type;
  8. namespace StructsValidator
  9. {
  10. class Program
  11. {
  12. static string codeContent;
  13. static void Main(string[] args)
  14. {
  15. //get all structs from Urho.dll
  16. var structs = typeof (UrhoObject).Assembly.GetTypes().Where(t => t.IsValueType && !t.IsPrimitive && !t.IsEnum).ToArray();
  17. // only those with Sequential layout and Sizeof > 1 (not empty)
  18. var notEmptyStructs = structs.Where(t => !t.IsAutoLayout && Marshal.SizeOf(t) > 1).ToArray();
  19. AppendC("// THIS CODE IS AUTOGENERATED BY SharpieBinder/StructsValidator\n");
  20. if (IntPtr.Size == 8)
  21. AppendC("#if defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__) // generated for x64 only\n");
  22. else
  23. AppendC("#if !defined(_WIN64) && !defined(__x86_64__) && !defined(__ppc64__) // generated for x86 only\n");
  24. AppendC("using namespace Urho3D;\n");
  25. AppendC("void check_bindings_offsets()\n{");
  26. foreach (var type in notEmptyStructs)
  27. AddTest(type);
  28. AppendC("}");
  29. AppendC("#endif");
  30. AppendC($"\n/* Empty structs (stubs?):\n\n {string.Join("\n ", structs.Where(t => Marshal.SizeOf(t) <= 1).Select(t => t.Name).ToArray())}\n\n*/");
  31. File.WriteAllText("../../../../bindings/src/asserts.h", codeContent);
  32. }
  33. static void AddTest(Type type)
  34. {
  35. var managedName = type.Name;
  36. var nativeName = ResolveUrhoType(managedName);
  37. if (nativeName == null)
  38. return;
  39. var size = Marshal.SizeOf(type);
  40. AppendC($"\n\t// {managedName}:");
  41. AppendC($"\tstatic_assert(sizeof({nativeName}) == {size}, \"{managedName} has wrong size ({size})\");");
  42. foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
  43. {
  44. var managedFieldName = field.Name;
  45. var nativeFieldName = ResolveUrhoTypeField(managedName, managedFieldName);
  46. var offset = Marshal.OffsetOf(type, managedFieldName);
  47. AppendC($"\tstatic_assert(offsetof({nativeName}, {nativeFieldName}) == {offset}, \"{managedName}.{managedFieldName} has wrong offset ({offset})\");");
  48. }
  49. }
  50. static string ResolveUrhoTypeField(string typeName, string fieldName)
  51. {
  52. fieldName = fieldName.Trim('_');
  53. fieldName = char.ToLowerInvariant(fieldName[0]) + fieldName.Substring(1);
  54. if (fieldName.EndsWith("Ptr"))
  55. fieldName = fieldName.Remove(fieldName.Length - 3);
  56. if (fieldName.EndsWith("Id"))
  57. fieldName = fieldName.Remove(fieldName.Length - 2) + "ID";
  58. if (typeName == "BiasParameters" && fieldName == "slopeScaleBias") return "slopeScaledBias_";
  59. if (typeName == "AnimationTriggerPoint" && fieldName == "variant") return "data_";
  60. if (typeName == "CompressedLevel" && fieldName == "imageData") return "data_";
  61. if (typeName == "CompressedLevel" && fieldName == "rowCount") return "rows_";
  62. if (typeName == "Matrix3") return fieldName.Replace("C","").Replace("r", "m") + "_";
  63. if (typeName != "CrowdObstacleAvoidanceParams")
  64. fieldName += "_";
  65. return fieldName;
  66. }
  67. static string ResolveUrhoType(string name)
  68. {
  69. string[] ignoredTypes = {
  70. //TODO: handle these types
  71. "BezierConfig",
  72. "CollisionData",
  73. "StringHashRef",
  74. "StringHash",
  75. "Iterator",
  76. "AttributeInfo",
  77. "ProfilerBlock",
  78. "WeakPtr",
  79. "VectorBase",
  80. "Variant",
  81. "Quaternion",
  82. "Matrix4",
  83. "UrhoString",
  84. "TypeInfo",
  85. "CascadeParameters",
  86. //??:
  87. "__StaticArrayInitTypeSize=16",
  88. "<Data>e__FixedBuffer",
  89. };
  90. if (name.EndsWith("EventArgs") || ignoredTypes.Contains(name))
  91. return null;
  92. if (name == "UrhoString")
  93. return "String";
  94. return name;
  95. }
  96. static void AppendC(string line)
  97. {
  98. codeContent += line + "\n";
  99. }
  100. }
  101. }