Program.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. using System;
  2. using System.Linq;
  3. using System.Reflection;
  4. using System.Runtime.InteropServices;
  5. using Urho;
  6. using Type = System.Type;
  7. namespace StructsValidator
  8. {
  9. class Program
  10. {
  11. static string codeContent;
  12. static void Main(string[] args)
  13. {
  14. //get all structs from Urho.dll
  15. var structs = typeof (UrhoObject).Assembly.GetTypes().Where(t => t.IsValueType && !t.IsPrimitive && !t.IsEnum);
  16. // only those with Sequential layout
  17. structs = structs.Where(t => t.IsLayoutSequential).ToArray();
  18. AppendC(
  19. @"using namespace Urho3D;
  20. void check_size(int actual, int expected, const char * typeName)
  21. {
  22. if (actual != expected)
  23. printf(""sizeof(%s) is %d but %d is expected"", typeName, actual, expected);
  24. }
  25. void check_offset(int actual, int expected, const char* typeName, const char* fieldName)
  26. {
  27. if (actual != expected)
  28. printf(""offset(%s, %s) is %d but %d is expected"", typeName, fieldName, actual, expected);
  29. }
  30. int main()
  31. {");
  32. foreach (var type in structs)
  33. {
  34. AddTest(type);
  35. }
  36. AppendC("}");
  37. //TODO: flush codeContent, compile and execute.
  38. }
  39. static void AddTest(Type type)
  40. {
  41. var managedName = type.Name;
  42. var nativeName = ResolveUrhoType(managedName);
  43. if (nativeName == null)
  44. return;
  45. var size = Marshal.SizeOf(type);
  46. AppendC($"\n\t// {managedName}:");
  47. AppendC($"\tcheck_size(sizeof({nativeName}), {size}, \"{managedName}\");");
  48. foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
  49. {
  50. var managedFieldName = field.Name;
  51. var nativeFieldName = ResolveUrhoTypeField(managedName, managedFieldName);
  52. var offset = Marshal.OffsetOf(type, managedFieldName);
  53. AppendC($"\tcheck_offset(offsetof({nativeName}, {nativeFieldName}), {offset}, \"{managedName}\", \"{managedFieldName}\");");
  54. }
  55. }
  56. static string ResolveUrhoTypeField(string typeName, string fieldName)
  57. {
  58. fieldName = fieldName.Trim('_');
  59. fieldName = char.ToLowerInvariant(fieldName[0]) + fieldName.Substring(1);
  60. if (fieldName.EndsWith("Ptr"))
  61. fieldName = fieldName.Remove(0, fieldName.Length - 3);
  62. if (typeName != "CrowdObstacleAvoidanceParams")
  63. fieldName += "_";
  64. return fieldName;
  65. }
  66. static string ResolveUrhoType(string name)
  67. {
  68. string[] ignoredTypes = {
  69. //TODO: handle these types
  70. "nuint",
  71. "nint",
  72. "BezierConfig",
  73. "CollisionData",
  74. "StringHashRef",
  75. "StringHash",
  76. "Iterator",
  77. "AttributeInfo",
  78. "ProfilerBlock",
  79. "WeakPtr",
  80. "VectorBase",
  81. "dtQueryFilter",
  82. "RandomAccessIterator",
  83. "Matrix3",
  84. "Matrix4",
  85. "Matrix4d",
  86. "Quaterniond",
  87. "Quaternion",
  88. "Vector2d",
  89. "Vector3d",
  90. "Vector4d",
  91. "UrhoString",
  92. "CascadeParameters",
  93. };
  94. if (name.EndsWith("EventArgs") || ignoredTypes.Contains(name))
  95. return null;
  96. if (name == "UrhoString")
  97. return "String";
  98. return name;
  99. }
  100. static void AppendC(string line)
  101. {
  102. codeContent += line + "\n";
  103. }
  104. }
  105. }