Изменение оформленных имен — переход с VS6.0 на VS2005

После нескольких часов гугления, я думаю, пришло время спросить экспертов. У нас есть устаревший модуль (MS Visual C++ 6.0), который мы пытаемся перенести на VS 2005. Существует ряд вызывающих приложений, поэтому мы пытаемся, если это возможно, сохранить их обратную совместимость.

С точки зрения кода это оказалось довольно просто, и несколько часов разработки устранили все ошибки компилятора и большинство предупреждений.

Затем я столкнулся с несколькими ошибками «неразрешенный внешний символ» на этапе связывания, которые кажутся тонкими различиями в оформленном имени.

Оказывается, один набор ошибок был связан с тем, что time_t является 64-битной структурой в VS2005 — определение _USE_32BIT_TIME_T исправило эти три.

Теперь я застрял с двумя оставшимися ошибками:

Функция определяется как

int RC_STATE::my_function(UINT stateId, UINT period, UINT index, UINT paramtype, UINT dpindex, UINT managerId, UINT calctype, UINT status, double *p_val, long *p_isc, CTime *p_time)

Оказывается, под "старой" Visual Studio его устраивало украшенное имя

?my_function@RC_STATE@@QAEHIIIIIIIIPANPAJPAVCTime@@@Z

Но теперь VS2005 хочет включить пространство имен ATL для параметра "CTime":

?my_function@RC_STATE@@QAEHIIIIIIIIPANPAJPAVCTime@ATL@@@Z

Если я обновлю свой файл .DEF с этим новым украшенным именем, он скомпилируется и линкуется... ура! За исключением того, что как только я загружаю эту DLL с каким-то кодом, который раньше работал, он жалуется, что не может найти точку входа в процедуру в DLL (то есть ту, что со «старой» структурой, без пространства имен).

Какие-либо предложения? Есть ли какое-то ключевое слово, директива компилятора, которая позволила бы мне сказать компилятору, чтобы он не помещал пространство имен в украшенное имя (я знаю, что пространства имен хороши, но нет никакого конфликта с типом CTime, которому потребовалось бы пространство имен для разрешить конфликт).

Есть ли обходные пути, чтобы украшенное имя соответствовало старому формату?

Заранее большое спасибо за любые предложения.


person meisen99    schedule 23.01.2009    source источник


Ответы (2)


На самом деле здесь две проблемы. Во-первых, CTime теперь находится в пространстве имен ATL, как вы уже обнаружили, но также CTime в VS2005 использует __time64_t для внутреннего использования, что составляет 64 бита, а не 32 бита, и это не меняется при определении _USE_32BIT_TIME_T.

Таким образом, даже если вы решили проблему с пространством имен, если ваше приложение скомпилировано с помощью VC6, а DLL скомпилирована с помощью VS2005 (или наоборот), передача CTime объектов между этими модулями почти наверняка приведет к проблемам с повреждением данных из-за разницы в макете памяти.

На мой взгляд, решение состоит в том, чтобы перекомпилировать весь ваш код с помощью VS2005 и везде использовать 64-битный time_t, соответствующий CTime в VS2005 (т. е. не использовать _USE_32BIT_TIME_T).

Надеюсь, это поможет!

person ChrisN    schedule 24.01.2009
comment
Спасибо, у меня было ощущение, что это будет лучший подход. Мне нужно определить, насколько практична перекомпиляция всех вызывающих приложений. Спасибо! - person meisen99; 25.01.2009

Другой возможностью было бы скопировать старое определение CTime в ваш проект VS2005 и использовать его в списке параметров функции, в которой вы пытаетесь сохранить совместимость. Затем преобразуйте обратно совместимый параметр CTime в новый ATL::CTime перед обработкой. Старые клиенты VC6 могут вызывать обратно совместимый метод.

person Aidan Ryan    schedule 25.01.2009
comment
Тоже хорошая идея. Я попробую это и посмотрю, помещает ли внутренняя версия CTime пространство имен в украшенное имя; надеюсь, что нет! - person meisen99; 25.01.2009
comment
Когда вы копируете определение, не помещайте его в какое-либо пространство имен, в основном просто перетащите старое определение прямо в ваш новый проект. - person Aidan Ryan; 25.01.2009