Здравствуйте.
Есть у меня задача написать большую dll с COM-классами на ATL для использования её в VB6 (иные варианты не рассматриваются, даже не предлагайте

).
Никогда этим ранее не занимался.
Начал с того, что создал в VS проект Windows DLL, добавил туда idl-файл и попробовал немного написать этот idl. На пробу, как первый шаг к дальнейшей работе. В первых строках данного файла примерно такое:
//VB-совместимость
typedef long DWORD;
typedef DWORD *LPDWORD;
typedef DWORD *PDWORD;
typedef short WORD;
typedef long UINT;
typedef long HWND;
typedef byte CHAR;
typedef byte UCHAR;
typedef wchar_t *PCWSTR;
typedef short WCHAR;
typedef long HDC;
typedef long HMONITOR;
typedef long HMODULE;
typedef long HANDLE;
typedef void* LPCVOID;
Далее идут всякие struct и interface (до фигища).
Разумеется, импорт виндовских типов MIDL делает сам из wtypes.idl, и мои переопределения идут после этого импорта.
Так вот, всё это прекрасно компилируется в tlb, и эта tlb прекрасно видится из VB6. Описал один coclass на пробу — создаётся, и методы вызываются.
Возрадовавшись, начал собственно основное — библу на ATL. Тут же оказалось, что все эти переопределения типов вызывают ошибку компиляции idl, а галка "MkTypLib Compatible", стоявшая в первом проекте, вообще не работает, ибо вызывает конфликт переопределения LIBID для самой library.
Долго сравнивал настройки проектов Windows dll и ATL (в основном, секцию MIDL). Чесал репу, но так ничего и не понял.
MSDN, опять же, но с тем же результатом.
Вот хочу спросить, как добиться от проекта ATL того же результата, как от WinDll. Чтобы работали мои переопределения.
Здравствуйте, GSerg, Вы писали:
GS>Здравствуйте.
GS>Есть у меня задача написать большую dll с COM-классами на ATL для использования её в VB6 (иные варианты не рассматриваются, даже не предлагайте
).
GS>Никогда этим ранее не занимался.
GS>Начал с того, что создал в VS проект Windows DLL, добавил туда idl-файл и попробовал немного написать этот idl. На пробу, как первый шаг к дальнейшей работе. В первых строках данного файла примерно такое:
GS>GS>//VB-совместимость
GS>typedef long DWORD;
GS>typedef DWORD *LPDWORD;
GS>typedef DWORD *PDWORD;
GS>typedef short WORD;
GS>typedef long UINT;
GS>typedef long HWND;
GS>typedef byte CHAR;
GS>typedef byte UCHAR;
GS>typedef wchar_t *PCWSTR;
GS>typedef short WCHAR;
GS>typedef long HDC;
GS>typedef long HMONITOR;
GS>typedef long HMODULE;
GS>typedef long HANDLE;
GS>typedef void* LPCVOID;
GS>
GS>Далее идут всякие struct и interface (до фигища).
GS>Разумеется, импорт виндовских типов MIDL делает сам из wtypes.idl, и мои переопределения идут после этого импорта.
GS>Так вот, всё это прекрасно компилируется в tlb, и эта tlb прекрасно видится из VB6. Описал один coclass на пробу — создаётся, и методы вызываются.
Подход не верен в принципе. VB6 нужны IDispatch интерфейсы, и ваши структуры и т.п. работать не будут. Кроме того, не будет работать typelibrary маршаллинг. Пакуйте структуры в интерфейсы и используйте только Automation types.
Здравствуйте, Аноним, Вы писали:
А>Подход не верен в принципе
Тогда не получилось бы создать VB-compatible tlb в проекте Windll.
А>VB6 нужны IDispatch интерфейсы
В корне неверное представление закоренелого сишника

VB отлично работает с IUnknown без дополнительных телодвижений, а с одним дополнительным телодвижением работает ещё и с не-IUnknown.
А>и ваши структуры и т.п. работать не будут.
Увы, они уже работают. Из проекта WinDLL
А>Кроме того, не будет работать typelibrary маршаллинг.
Увы, работает и он
А>Пакуйте структуры в интерфейсы и используйте только Automation types.
Так вот только для введения Automation types всё и затевается.
Если VB увидит в tlb тип unsigned long, он скажет: <unsupported automation type>. Поэтому, когда мы из VB ведём диалог с сишными прогами, ожидающими ULONG, мы передаём наш обычный LONG, просто помним, что на самом деле он U.
И под структурами я подразумевал пользовательские типы. Контсрукцию struct из tlb VB трактует как свой Type (и правильно делает). У меня нет намерения использовать struct в качестве замены интерфейсу. Интерфейсы — они отдельно.
Понимаете, я могу во всей tlb руками разменить все ULONG на long и т.д. Но я не хочу этого делать, т.к. знаю, что можно через typedef. Я понимаю, что с точки зрения сишников подход может казаться странным, но тем не менее всё годами работает именно так.
Поэтому повторю первоначальный вопрос — как заставить typedef работать в проекте ATL так же, как он работает в WinDLL?
Здравствуйте, GSerg, Вы писали:
GS>Долго сравнивал настройки проектов Windows dll и ATL (в основном, секцию MIDL). Чесал репу, но так ничего и не понял.
GS>MSDN, опять же, но с тем же результатом.
Потому что генерируемые здесь (т.е. для Windows dll) файлы (всякие там h и c) не используются в создании рабочего кода и фактически не обрабатываются компилятором С++, т.к. используется только генерируемая TLB как описание функций Windows.
GS>Вот хочу спросить, как добиться от проекта ATL того же результата, как от WinDll. Чтобы работали мои переопределения.
Обычно такие замены в IDL обрамляются в скобки с тем, чтобы реально использовались реальные типы (из windows.h), а не их подмены в TLB:
cpp_quote("#if 0")
typedef long DWORD;
...
cpp_quote ("#endif")
Спорить не буду — лень. Дело ваше — положите кучу усилий, а потом ничего работать не будет. Вы где-нибудь видели такой подход к написанию компонентов для VB? A почему никто и никогда так не делает?