Почему при попытке присвоить варианту массив для какого-либо объекта, не подверженного IDispatch, вместо него назначается указатель массива? - PullRequest
5 голосов
/ 15 мая 2019

Сводка

После объявления массива для некоторого типа объекта, в котором тип не использует интерфейс, который получает из COM 's IDispatch интерфейс (и поэтому неправильно настроен для включения технологии позднего связывания [OLE] Automation ), пытаясь назначить массив для Variant переменная не работает в соответствии с моими ожиданиями.

В частности, похоже, что целочисленный указатель на массив назначен Variantпеременная, а не копия массива.

Может кто-нибудь объяснить такое поведение?Это стандартное поведение языка VBA 7.1? [EDIT-A1] Это тип VBA Variant не может обрабатывать такие массивы? [EDIT-A2]


[EDIT-A1] - В настоящее время (04/6/19),похоже, что это ошибка.
[EDIT-A2] - Нет, поскольку внутренние параметры процедуры для аргументов ByRef Variant могутправильно указывать на такие массивы, если такие массивы передаются в качестве значений для таких аргументов.



Фон

Подробнее о том, что, по-видимому, происходит

После проверки различных адресов и указателей памяти, похоже, что при назначении таких массивов переменным Variant, Long (или LongPtr) указатели на 'указатели безопасного массива VB' массивов назначаются вместо этого.Это противоречит поведению копирования массива, задокументированному здесь в спецификации языка VBA как ожидаемое поведение.Я пришел к выводу, что такое присвоение указателя происходило после просмотра документации VB6 по массивам VB и их разметке памяти, хранящейся здесь .

Мое исследование того, была ли ранее задокументирована проблема

Я искал в Интернете, Office VBA Reference документацию, а также спецификацию языка VBA , чтобы узнать, задокументирована ли эта проблема кем-либо еще.Единственное место, где я обнаружил, что эта проблема, возможно, уже была частично задокументирована, это ответ на переполнение стека, размещенный здесь .К сожалению, пост не говорит много о проблеме.

Определенные типы массивов, с которыми я тестировал эту проблему

Я столкнулся с этой проблемой с массивами следующих типов объектов, которые не используют интерфейсы вывод из IDispatch:

  • stdole.IUnknown *
  • stdole.IFont
  • mscoree.CorRuntimeHost
  • mscorlib.AppDomain
  • mscorlib.Type

* Из библиотеки типов OLE Automation COMв stdole2.tlb.
† Из библиотеки типов COM для .NET framework v4.0.30319.

Подробнее о типе объекта, который использует интерфейс, не производный от IDispatch, является

Такими типами объектов являются vbDataObject типы.К сожалению, текущая документация VBA по константе vbDataObject является неточной.Я нахожусь в процессе обновления документации, и вы можете увидеть мое обновленное определение для константы здесь .

[ПРАВКА - ссылка на спецификацию COM удалена, поскольку она больше не актуальна.]


Относительно массивов других типов объектов

Массивы типов vbObject (типы объектов COM, поддерживающие технологию позднего связывания [OLE] Automation), по-видимому, назначены на Variant переменные в прямом и ожидаемом порядке - массив копируется и присваивается напрямую

Сбой VBE при проверке таких массивов с использованием часов VBE

Потенциально связанная проблема связана с ошибкой, которая возникала, когда VBE наблюдательное выражение было помещено в массив типа, который использовал интерфейс, а не вывод из IDispatch.Ошибка, используемая для неожиданного сбоя VBE.Эта ошибка, похоже, была исправлена ​​Microsoft в течение последнего месяца.

Версии программного обеспечения

<strong>Software</strong>               | <strong>Version</strong>      
-------------------------+---------------<br>  VBA                    | 7.1 <sup>‡</sup><br>-------------------------+---------------<br>  Microsoft Excel        | 2016 <sup>§</sup><br>-------------------------+---------------<br>  Microsoft Windows (OS) | 8.1 <sup>¶</sup> 

‡ Полный текст для версии «Retail 7.1.1088» - последняя версия.
§ В частности, последняя версия и сборка (выпущена 3 июня 2019 г., версия 1905, сборка 11629.20214), а также более ранние номера сборок 11629.20196 и 11601.20204 (первая была выпущена14 мая 2019 г.)
ver.exe программа печатает "Microsoft Windows [Версия 6.3.9600]" .

Код

Представляет :

    Dim MyArray() As stdole.IUnknown ' Type from OLE Automation 
                                     ' COM type library in stdole2.tlb.
    Dim MyVariant As Variant
    MyVariant = MyArray

Я ожидал, что MyVariant сохранит копию массива MyArray.

Вместо этого в 32-битномверсия VBA, MyVariant хранит значение Long, которое выглядит как указатель на MyArray.

Проблема отладки

Нажмите здесь , чтобы код VBA могпомочь в устранении проблемы.

...