Отказ от ответственности : Я не эксперт по IDL (Язык определения интерфейса, который используется для определения типов COM) или компилятору Microsoft IDL (MIDL), но я пришел квыводы ниже, после игры с библиотекой типов для scrrun.dll, которая имеет аналогичную проблему с enum.Часть этой информации была получена из краткого обзора этой статьи DevX по IDL и VB6: IDL для VB Tutorial
VB6 ожидает, что фактическое перечисление будет иметь имя, а не простоперечисление, которое typedef
соответствует имени.Имя __MIDL___MIDL_itf_autosvcs_0469_0002
является заполнителем, так как исходная библиотека типов не определила имя перечисления в том же typedef
, где определены константы перечисления.
Когда вы просматриваете библиотеку типов в OLE Viewer,enum
, вероятно, выглядит так:
typedef [public] __MIDL___MIDL_itf_autosvcs_0469_0002 LockModes;
typedef enum {
LockSetGet = 0,
LockMethod = 1
} __MIDL___MIDL_itf_autosvcs_0469_0002;
Первый typedef
создает публичное имя LockModes
в качестве псевдонима для автоматически сгенерированного MIDL___MIDL_itf_autosvcs_0469_0002
имени, которое было присвоено enum
.Когда исходная библиотека типов была скомпилирована, компилятор midl
сгенерировал длинное имя __MIDL
для исходного enum
и автоматически создал псевдоним typedef
, указывающий на него.
Исходный IDL, вероятно, определил перечисление следующим образом:
typedef enum {
LockSetGet = 0,
LockMethod = 1
} LockModes;
Когда компилятор midl
обрабатывает определение enum
, написанное таким образом, он автоматически генерирует имя для enum
(поскольку он отсутствует - он должен появляться после ключевого слова enum
).Это имя __MIDL
, которое вы видите при просмотре библиотеки типов в OLE Viewer.Компилятор midl
также автоматически генерирует вторую typedef
, которая связывает имя typedef
с автоматически сгенерированным именем enum
.
Проблема состоит в том, что VB6 не может понять перечисления, созданные этимпуть.Он ожидает, что все будет в одном typedef
(то есть вы даете enum
имя, а также присваиваете имя typedef
):
typedef enum LocksMode {
LockSetGet = 0,
LockMethod = 1
} LocksMode;
IDL обрабатывает typedef
то же самоеКак это делает C или C ++: вам не нужно присваивать самому enum имя, потому что typedef
уже имеет имя, но вы можете дать enum имя, если вы выберете.Другими словами, typedef
и enum
на самом деле являются двумя отдельными сущностями.VB6 случайно распознает typedef
и enum
как две разные, но неопределенно связанные вещи, поэтому в вашем случае он видит typedef
с именем __MIDL___MIDL_itf_autosvcs_0469_0002
и видит, что это псевдоним неназванногоenum, и он также видит typedef
для LockModes
, который является общедоступным псевдонимом для другого typedef
.
Поскольку первый typedef
является общедоступным, вы увидите запись для LockModes
в обозревателе объектов, и поскольку это псевдоним для перечисления, вы также увидите константы перечисления в обозревателе объектов.Тем не менее, само фактическое перечисление не имеет имени (поэтому он получает фанки автоматически сгенерированного имени, назначенного ему в браузере), и VB6 не может использовать перечисление, потому что автоматически сгенерированное имя происходитбыть недопустимым в VB6 (имена с двойным подчеркиванием автоматически скрываются в VB6).
Чтобы продемонстрировать эту последнюю точку, если вы введете это в коде VB6, Intellisense будет работать и компилироваться, но, очевидно,он не очень идеален:
MsgBox COMSVCSLib.[__MIDL___MIDL_itf_autosvcs_0469_0002].LockMethod
Причина, по которой этот код работает, заключается в том, что вы можете помещать имена, которые обычно вызывают синтаксические ошибки (например, имена, начинающиеся с подчеркиваний), в скобках, чтобы VB6 мог принимать обычно незаконныеназвание.Кроме того, префикс констант с автоматически сгенерированным именем работает с Intellisense, потому что это фактическое имя, которое VB6 связывает с enum
(помните, что typedef
- это просто псевдоним этого «реального», но автоматическисгенерированное имя, и VB6, по-видимому, не может собрать все части вместе, чтобы понять, что оба имени относятся к одному и тому же enum
).
Вместо того, чтобы вводить смехотворно длинное имя, как указано выше, вы также можете получить доступ к enum
констант, добавив к ним префикс имени библиотеки, например, COMSVCSLib.LockMethod
, должно работать.Мне менее понятно, почему это действительно работает, и я не уверен, что произойдет, если два разных enum
определяют константы с одинаковым именем.
Наконец, вы можете решить эту проблему по-другому, используя IDL из OLE Viewer для создания пользовательского файла IDL, в котором вы заменяете существующие enum
typedefs на typedef
для каждого enum
, который просто дает как enum
, так и typedef
одно и то же имя (т.е. typedef enum LockModes { ... } LockModes;
), но поскольку OLE Viewer не обязательно генерирует действительный IDL, вам, вероятно, придется настроить его еще больше, чтобы он действительно компилировался , Если вы можете заставить это работать, то вы можете ссылаться на ваш пользовательский .tlb
из вашего проекта VB6 (вместо библиотеки COMSVCSLib
), и enum
будут работать так, как вы ожидаете.
Если вы хотите пойти по этому пути, вам нужны еще два инструмента, которые уже должны быть установлены на вашем компьютере разработчика (но вам, возможно, придется их искать):
midl.exe
: Этот инструмент может генерировать файл typelib (* .tlb) из файла .idl
. Таким образом, вы можете скопировать IDL из OLE Viewer в Блокнот, изменить определения enum, как описано выше, сохранить его как файл .idl
и передать его в midl.exe
для создания новой библиотеки типов:
midl my-custom-typelib.idl
regtlib.exe
: Этот инструмент может зарегистрировать файл .tlb, который необходим, если вы хотите добавить его в качестве ссылки на ваш проект VB6:
regtlib.exe my-custom-typelib.tlb
Однако создание пользовательской библиотеки типов для этого, вероятно, излишне, и, как уже упоминалось, может быть трудно получить скомпилированный файл IDL, основанный на выводе из OLE Viewer, поскольку он отображает IDL с обратной инженерией для библиотеки типов , а не оригинальный IDL.