Sergei I. Gorelkin » 21.11.2010 06:17:09
Попробую по порядку:
- В генерации сдвига в компиляторе был тупой баг, считалось что все передается по ссылке и под каждый аргумент отводилось sizeof(pointer) байт, хотя double передавался по значению и для него нужно sizeof(double). Из-за этого на x86_64, собственно, все было хорошо, а на i386 твой патч не работал. Это я поправил в ревизии 16350.
- Потом в ревизии 16360 я в добавил проверки в парсинг dispinterface, чтобы в них можно было использовать только automatable типы. Заодно убрал ограничения времен windows 95 на перечисляемые типы, и решил проблему не-передачи перечисляемых типов по ссылке. Т.к. вызовы методов variant полностью динамические и для них нет объявлений с указанием как что передавать, то используется следующая логика: если можно передать по ссылке, то передаем по ссылке, иначе по значению. А по ссылке можно передавать все, кроме результата вызова другой функции, свойств и непосредственно заданных значений.
- Затем нужно было забороть тип variant, который всегда передавался по ссылке. Что и было сделано в 16389. В параметрах по-прежнему передается ссылка, но бит $80 устанавливается не всегда. Из-за этого в патч для DispInvoke придется вносить изменения, аналогичные тем, что внесены в winunits-base/src/comobj.pp ревизии 16388. Но это я и сам могу сделать.
Теперь эта UnicodeString, будь она неладна. Ее я даже еще не начинал копать. Но уже понятно, что с ней надо обходиться примерно так, как с AnsiString. Откуда растут ноги у varString и varStrArg? varString=$100, т.е. находится в диапазоне "псевдо-пользовательских" типов. "Псевдо" - потому что настоящий TCustomVariant начинается с $10F. А находится в этом диапазоне потому, что это специфичный для Delphi/FPC тип, и COM с ним работать просто не умеет.
А varStrArg используется только для передачи типа AnsiString в DispInvoke, потому что в CallDesc на каждый аргумент отводится только 1 байт, и varString в него просто не помещается.
Т.е, действуя по образу и подобию, нужно изменять varUnicodeString на $102 (кстати в последних Delphi оно так и есть, только имя varUString), добавлять какой-нибудь varUStrArg=73, и дальше по аналогии...
Что с этой радостью делать в самой процедуре DispInvoke - тоже непонятно. Просто так подставлять varOleStr вместо varUnicodeString нельзя, это разные типы, нужно выделять память с помощью SysAllocateString и копировать строку туда, но это возможно только для windows...