Program.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. bool is64 = IntPtr.Size == 8;
  20. AppendC("// THIS CODE IS AUTOGENERATED BY SharpieBinder/StructsValidator\n");
  21. AppendC(is64
  22. ? "#if defined(_MSC_VER) && (defined(_WIN64) || defined(__x86_64__) || defined(__ppc64__)) // generated for x64 only\n"
  23. : "#if defined(_MSC_VER) && !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/Native/asserts_" + (is64 ? "64.h" : "32.h"), codeContent);
  32. }
  33. static void AddTest(Type type)
  34. {
  35. if (type.FullName.StartsWith("Urho.SharpReality") ||
  36. type.FullName.StartsWith("Urho.Holo"))
  37. return;
  38. var managedName = type.Name;
  39. var nativeName = ResolveUrhoType(managedName);
  40. if (nativeName == null)
  41. return;
  42. var size = Marshal.SizeOf(type);
  43. AppendC($"\n\t// {managedName}:");
  44. AppendC($"\tstatic_assert(sizeof({nativeName}) == {size}, \"{managedName} has wrong size ({size})\");");
  45. foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
  46. {
  47. var managedFieldName = field.Name;
  48. var nativeFieldName = ResolveUrhoTypeField(managedName, managedFieldName);
  49. if (string.IsNullOrEmpty(nativeFieldName))
  50. continue;
  51. var offset = Marshal.OffsetOf(type, managedFieldName);
  52. AppendC($"\tstatic_assert(offsetof({nativeName}, {nativeFieldName}) == {offset}, \"{managedName}.{managedFieldName} has wrong offset ({offset})\");");
  53. }
  54. }
  55. static string ResolveUrhoTypeField(string typeName, string fieldName)
  56. {
  57. fieldName = fieldName.Trim('_');
  58. fieldName = char.ToLowerInvariant(fieldName[0]) + fieldName.Substring(1);
  59. if (fieldName.EndsWith("Ptr")) fieldName = fieldName.Remove(fieldName.Length - 3);
  60. if (fieldName.EndsWith("Id")) fieldName = fieldName.Remove(fieldName.Length - 2) + "ID";
  61. if (typeName == "VariantValue") return null; //it's complicated, let's just verify it's sizeof
  62. if (typeName == "BiasParameters" && fieldName == "slopeScaleBias") return "slopeScaledBias_";
  63. if (typeName == "AnimationTriggerPoint" && fieldName == "variant") return "data_";
  64. if (typeName == "CompressedLevel" && fieldName == "imageData") return "data_";
  65. if (typeName == "CompressedLevel" && fieldName == "rowCount") return "rows_";
  66. if (typeName == "Matrix3") return fieldName.Replace("C","").Replace("r", "m") + "_";
  67. if (typeName == "RenderPathCommand" && fieldName.StartsWith("textureName")) return string.Empty;
  68. if (typeName != "CrowdObstacleAvoidanceParams") fieldName += "_";
  69. return fieldName;
  70. }
  71. static string ResolveUrhoType(string name)
  72. {
  73. string[] ignoredTypes = {
  74. "CustomGeometryVertex",
  75. "VariantValueLine",
  76. "BezierConfig",
  77. "CollisionData",
  78. "StringHashRef",
  79. "StringHash",
  80. "Iterator",
  81. "AttributeInfo",
  82. "ProfilerBlock",
  83. "WeakPtr",
  84. "VectorBase",
  85. "Variant",
  86. "Quaternion",
  87. "Matrix4",
  88. "UrhoString",
  89. "TypeInfo",
  90. "HashBase",
  91. "CascadeParameters",
  92. };
  93. if (name.EndsWith("EventArgs") ||
  94. ignoredTypes.Contains(name) ||
  95. name.Contains("PositionNormal") ||
  96. //code-generated structs:
  97. name.Contains("__StaticArrayInitTypeSize") ||
  98. name.Contains("__FixedBuffer"))
  99. return null;
  100. if (name == "UrhoString")
  101. return "String";
  102. return name;
  103. }
  104. static void AppendC(string line)
  105. {
  106. codeContent += line + "\n";
  107. }
  108. }
  109. }