|
|
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Я уже дважды сталкивался с несовместимостью кода на XE. Это работа с отрицательным TDateTime и реализацией интерфейсов через property implements. В обоих случаях эмбаркадера исправила старые ошибки, но это были те баги, которые уже воспринимались как фичи. В обоих случаях мне понадобился день на рихтовку всего своего кода. Я не знаю, как нужно делать правильно, но один день - это не повод рыдать, что "все пропало" ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 13:15 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_реализацией интерфейсов через property implements. В обоих случаях эмбаркадера исправила старые ошибки, но это были те баги, которые уже воспринимались как фичи Можно поподробнее? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 14:53 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Kazantsev Alexey_Vasilisk_реализацией интерфейсов через property implements. В обоих случаях эмбаркадера исправила старые ошибки, но это были те баги, которые уже воспринимались как фичи Можно поподробнее?Раньше QueryInterface вызывался у того объекта, которые реализовывал интерфейс, сейчас ВСЕГДА вызывается у основного объекта Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. В 2007 выделенная строка работала, в ХЕ3 перестала Я перешел с 2007 на XE3, поэтому не могу сказать в какой именно версии это изменилось ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 16:00 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Раньше QueryInterface вызывался у того объекта, которые реализовывал интерфейс, сейчас ВСЕГДА вызывается у основного объекта Прикольная ситуация. Сейчас потрейсил 2007 и XE3 на предмет работы Implements. Там действительно довольно странно формируются vtbl's (кому интересно трейсите GetInterface, прикол в том, что ветка InvokeImplGetter не отрабатывает ни разу, т.е. ни в 2007 ни в XE3 implements не работает, как было задумано изначально. Правда, на первый взгляд, в 2007 ещё и крайне не эффективно), что в 2007, что в XE3. Однако, если использовать для агрегируемых интерфейсов в качестве родителя базовый TAggregatedObject, то внешне код работает одинаково. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 17:27 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Kazantsev AlexeyОднако, если использовать для агрегируемых интерфейсов в качестве родителя базовый TAggregatedObject, то внешне код работает одинаково.Ну дык Код: pascal 1. 2. 3. 4. Если мне не изменяет память, то с _AddRef и _Release то же самое. Т.е. стал использоваться счетчик ссылок родителя. Иными словами, все интерфейсы стали агрегируемые Kazantsev Alexeyimplements не работает, как было задумано изначальноА как было задумано? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 19:19 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Ну дык Это понятно. Тут другой вопрос, почему у тебя не от TAggregatedObject наследование было сделано, ведь он для целей аггрегации и предназначен. _Vasilisk_А как было задумано? Следуя логике GetInterface, если в таблице интерфейсов класса найдена запись в которой нет ссылки на vtbl (т.е. это те самые интерфейсы implemets...), то должен быть вызван метод InvokeImplGetter, который, в свою очередь, основываясь на флагах получит vtbl из поля объекта или через вызов геттера. Сейчас этот механизм не работает. На примере 2007 это очень хорошо видно - она на каждый чих с аггрегируемым интерфейсом зовёт геттер. О чём это говорит? О том, что компилятором формируется специальная vtbl, которая имеет ссылки на методы в, грубо говоря, таком виде: _AddRef - > InvokeGetter + _AddRef; В XE3 немного по другому, там IUnknown ссылается на родительский класс, а для кастомных методов работает механизм аналогичный 2007. Дурдом. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 19:56 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Сейчас проверил FPC 3.1.1 c этим кодом и логированием. Всё работает ровно так, как оно ожидается. Код для FPC Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. Вывод: Код: plaintext 1. 2. 3. 4. 5. Ну что за криворучки пилять дульфу... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 20:14 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
А это вывод 2007: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. XE3: Код: plaintext 1. 2. 3. 4. 5. 6. XE8: Код: plaintext 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 20:39 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Kazantsev AlexeyТут другой вопрос, почему у тебя не от TAggregatedObject наследование было сделаноНе будем о плохом. Проекту больше 10 лет. Видел бы ты, какие там костыли используются... Kazantsev AlexeyА это вывод 2007:Но это же полный сюр. Ты хочешь сказать, что каждый раз при вызове метода дочернего интерфейса создается новый объект? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 23:09 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Но это же полный сюр. Ты хочешь сказать, что каждый раз при вызове метода дочернего интерфейса создается новый объект? Всякий раз дёргается геттер. Ну а если в геттере создаётся объект... Это и правда полный сюр ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.07.2015, 23:17 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Ха-ха-ха! Delphi XE3 Test1 Source Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. Test1 Output Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. Test2 Source Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. Test2 Output Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. Test3 source Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Test3 Output Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Test4 Source Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Test4 Output Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Все тесты специально обернуты в процедуру Test, чтобы освободились все интерфейсные ссылки Справедливости ради, следует отметить, что, обычно, геттеры пишутся так Код: pascal 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 11.07.2015, 20:25 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Я перешел с 2007 на XE3, поэтому не могу сказать в какой именно версии это изменилось Я проверил, поведение изменилось именно в XE3. _Vasilisk_ Test4 Source Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Test4 Output Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. И что ещё прикольно, в случае прямого указания использования интерфейсных типов отрабатывает InvokeImplGetter. Кстати, утечка при использовании TAggregatedObject это не утечка на самом деле, просто агрегируемые объекты считаются частью агрегирующего класса, а потому должны быть освобождены явно, в деструкторе. _Vasilisk_Справедливости ради, следует отметить, что, обычно, геттеры пишутся так Код: pascal 1. 2. 3. 4. 5. 6. Зависит от. Легко можно представить ситуацию, где делегируемый интерфейс реализуется свободно отчуждаемым кодом т.е. объект реализующий его не является частью состояния делегирующего объекта. У меня, кстати, такой код есть, правда автоматизированное делегирование (implements) там не используется (сделано через QueryInterface). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.07.2015, 11:02 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Kazantsev Alexeyутечка при использовании TAggregatedObject это не утечка на самом деле, просто агрегируемые объекты считаются частью агрегирующего класса, а потому должны быть освобождены явно, в деструкторе.Да. Но вот утечка с TInterfacedObject не объяснима Kazantsev AlexeyЛегко можно представить ситуацию, где делегируемый интерфейс реализуется свободно отчуждаемым кодом т.е. объект реализующий его не является частью состояния делегирующего объекта.Не знаю. Я считаю такой подход ошибкой в архитектуре. Это лучше делать через Get-метод интерфейса ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.07.2015, 12:39 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Да. Но вот утечка с TInterfacedObject не объяснима Если ты об утечке, когда геттер возвращает объект, а не интерфейс, то она объясняется перенаправлением IUnknown на делегирующий объект. Сделали, видимо, для уменьшения различий в поведении с ситуацией, когда делегируются объекты вообще не поддерживающие интерфейсы. То есть, если нет явного получения интерфейса, то считается, что делегируется просто объект (т.е. его методы для реализации интерфейса), даже в том случае если он имеет собственную реализацию IUnknown. Однако, поломали обратную совместимость. _Vasilisk_Не знаю. Я считаю такой подход ошибкой в архитектуре. Это лучше делать через Get-метод интерфейса Случаи, опять же, разные бывают. А семантика методов Get и Query очень различается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 13.07.2015, 13:51 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
И еще на одни грабли наступил. Два совершенно разных интерфейса, но с одинаковым методом Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. (полный список методов может быть произвольным) Реализация Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. вывод D2007TIntf2 TIntf1DXE3TIntf2 TIntf2 При этом, если методы будут различаться по входным параметрам или возвращаемому результату, то все будет работать правильно Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. DXE3TIntf2 1Даже изменение соглашения о вызове заставляет систему работать адекватно Код: pascal 1. 2. 3. 4. 5. 6. 7. 8. 9. DXE3TIntf2 TIntf1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.12.2017, 19:58 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
Ну здесь какбэ ССЗБ. Нэймрезолвинг для интерфейсов для того и придуман, чтоб такой путаницы не было. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 19.12.2017, 22:44 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
А это не баг, случаем? Мож на QP его? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.12.2017, 01:40 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
white_niggerНэймрезолвинг для интерфейсов для того и придуман, чтоб такой путаницы не было.Ничего не понял. Какой неймрезолвинг? Я обращаюсь к конкретному методу конкретного интерфейса. GunSmokerМож на QP его?Проверить бы его на Токио ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.12.2017, 14:31 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Проверить бы его на Токио Да, на последнем билде (25.0.29039.2004) воспроизводится. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.12.2017, 17:14 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_Ничего не понял. Какой неймрезолвинг? Я обращаюсь к конкретному методу конкретного интерфейсаСорри, просмотрел тонкости. Кстати вопрос остаётся, если для реализации использовать нэймрезолвинг, что-нибудь изменится? Завтра на Токио гляну... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 20.12.2017, 20:16 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
GunSmokerА это не баг, случаем? Мож на QP его? это не баг, это правильно владеющий объект может переопределить любой метод implements, собственно это и исправлено в XE3 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2017, 09:10 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)владеющий объект может переопределить любой метод implements, собственно это и исправлено в XE3 Да, похоже разное поведение в зависимости от того, как описано поле: как класс или как интерфейс: implements : автор Delegating to an Interface-Type Property The delegate property must return an object whose class completely implements the interface specified by the implements directive, and which does so without method resolution clauses. Delegating to a Class-Type Property If the delegate property is of a class type, that class and its ancestors are searched for methods implementing the specified interface before the enclosing class and its ancestors are searched. Thus it is possible to implement some methods in the class specified by the property, and others in the class where the property is declared. Method resolution clauses can be used in the usual way to resolve ambiguities or specify a particular method. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2017, 13:00 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
kealon(Ruslan)владеющий объект может переопределить любой метод implementsМдя. Спасибо, буду знать kealon(Ruslan)собственно это и исправлено в XE3И опять на тему, что некоторые баги лучше не исправлять ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2017, 18:18 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_, поменяй FIntf1: TIntf1; на FIntf1: IIntf1; Не? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2017, 18:51 |
|
||
|
Изменился способ вызова (экземпляр класса) для QueryInterface
|
|||
|---|---|---|---|
|
#18+
_Vasilisk_kealon(Ruslan)собственно это и исправлено в XE3И опять на тему, что некоторые баги лучше не исправлятьэто серьёзный баг был Фактически старое поведение, после исправления, я могу повторить довольно легко (зачем только непонятно) Для обхода этого бага на XE2 придётся для вмещающего интерфейса вручную писать стабы к каждому методу, а для объекта reintroduce-ить методы, которые я хочу заменить, на пустые заглушки. Пусть лучше это компилятор делает. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 21.12.2017, 19:02 |
|
||
|
|

start [/forum/topic.php?fid=58&msg=39573950&tid=2041413]: |
0ms |
get settings: |
9ms |
get forum list: |
18ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
178ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
70ms |
get tp. blocked users: |
1ms |
| others: | 249ms |
| total: | 544ms |

| 0 / 0 |
