Как подготовиться к 64-битам при переходе на Delphi 2010 и Unicode

В 64-битной версии не ожидается поддержка 64-битной версии, которая больше не может ждать возможности перенести нашу существующую базу кода в unicode и 64-bit за один раз. Однако было бы неплохо, если бы мы уже подготовили наш код для 64-бит при выполнении перевода в Юникод. Это позволит свести к минимуму воздействие в случае, если оно наконец появится в версии 2020. Любые предложения, как подойти к этому, не внося много шума, если он не появится до 2020 года?

Ответ 1

Там другой подобный вопрос, но я также повторю свой ответ здесь, чтобы убедиться, что многие люди видят эту информацию:

Прежде всего, отказ от ответственности: хотя я работаю на Embarcadero. Я не могу говорить за своего работодателя. То, что я собираюсь написать, основано на моем собственном мнении о том, как должна работать гипотетическая 64-разрядная Delphi, но могут быть или не быть конкурирующие мнения и другие предусмотренные или непредвиденные несовместимости и события, которые вызывают альтернативные дизайнерские решения.

Это сказало:

  • Существует два целочисленных типа: NativeInt и NativeUInt, размер которых будет плавать между 32-битными и 64-битными в зависимости от платформы. Они были вокруг довольно много выпусков. Никакие другие целочисленные типы не изменят размер в зависимости от битности цели.

  • Убедитесь, что в любом месте, которое полагается на значение указателя, integer или наоборот использует NativeInt или NativeUInt для целого числа тип. TComponent.Tag должен быть NativeInt в более поздних версиях Delphi.

  • Я бы предложил не использовать NativeInt или NativeUInt для значений, не содержащих указателей. Постарайтесь, чтобы ваш код семантически совпал между 32-битным и 64-битным. Если вам нужно 32 бита диапазона, используйте Integer; если вам нужны 64 бита, используйте Int64. Таким образом, ваш код должен работать одинаково на обеих битах. Только если вы используете значение типа указателя какого-либо типа, например ссылку или THandle, следует использовать NativeInt.

  • Пойнтер-подобные вещи должны следовать аналогичным правилам указателям: объект (очевидно), но также такие вещи, как HWND, THandle и т.д.

  • Не полагайтесь на внутренние детали строк и динамических массивов, например их данные заголовка.

  • Наша общая политика по изменениям API для 64-разрядной версии должна состоять в том, чтобы сохранить один и тот же API между 32-битными и 64-битными, если это возможно, даже если это означает, что 64-битный API не обязательно использует машину. Для Например, TList, вероятно, будет обрабатывать MaxInt div SizeOf (Pointer) элементов, чтобы сохранить Count, индексы и т.д. как Integer. Поскольку Тип Integer не будет плавать (т.е. Изменить размер в зависимости от битности), мы не хотят иметь волновой эффект на код клиента: любые индексы, которые round-tripped через переменную типа Integer или индекс for-loop, будет усекаться и потенциально вызвать тонкие ошибки.

  • Если API-интерфейсы расширены для 64-разрядных, они, скорее всего, будут выполнены с помощью дополнительную функцию/метод/свойство для доступа к дополнительным данным, и это API также будет поддерживаться в 32-разрядной версии. Например, стандарт Length() процедура, вероятно, вернет значения типа Integer для аргументов тип строки или динамический массив; если кто-то хочет иметь дело с очень большими динамических массивов, может быть и процедура LongLength(), чья реализация в 32-бит такая же, как Length(). Длина() будет бросать исключение в 64-битном, если применяется к динамическому массиву с более чем 232 элементы.

  • В связи с этим, вероятно, будет улучшена проверка ошибок для сужение операций на языке, особенно сужение 64-битных значений до 32-разрядных местоположений. Это повлияло бы на удобство назначения возвращаемое значение Length для местоположений типа Integer, если Length(), вернулся Int64. С другой стороны, специально для компилятора-магии функции, такие как Length(), может быть какое-то преимущество магии, например, переключите тип возврата на основе контекста. Но преимущество не может быть аналогично взяты в не магических API.

  • Динамические массивы, вероятно, поддерживают 64-битную индексацию. Обратите внимание, что Java массивы ограничены 32-разрядной индексацией даже на 64-битных платформах.

  • Строки, вероятно, будут ограничены 32-разрядной индексацией. У нас есть время придумывает реалистичные причины для людей, желающих 4GB + строки это действительно строки, а не только управляемые капли данных, для которых динамические массивы могут также служить.

  • Возможно, встроенный ассемблер, но с ограничениями, например, неспособный свободно смешивать с кодом Delphi; существуют также правила вокруг исключений и макета фрейма стека, которые должны соблюдаться на x64.

Ответ 2

Сначала просмотрите места, где вы взаимодействуете с не-delphi-библиотеками и api-вызовами, они могут отличаться. В Win32 библиотеки со стандартным вызовом stdcall называются _SomeFunction @4 (@4, указывающие размер параметров и т.д.). На Win64 существует только одно соглашение о вызове, а функции в dll больше не оформлены. Если вы импортируете функции из DLL файлов, вам может потребоваться их настройка.

Имейте в виду, что в 64-разрядной версии EXE вы не можете загрузить 32-разрядную DLL, поэтому, если вы зависите от сторонних DLL файлов, вы должны проверить и 64-разрядную версию этих файлов.

Кроме того, посмотрите на Integers, если вы зависите от их максимального значения, например, когда вы позволяете им переполняться и ждать момента, когда это происходит, это вызовет проблему, если размер целого будет изменен.

Кроме того, при работе с потоками и вы хотите сериализовать разные данные, включая целое число, это вызовет проблему, так как размер целого изменился, и ваш поток будет не синхронизирован.

Итак, в местах, где вы зависите от размера целого или указателя, вам нужно будет внести коррективы. При сериализации данных sush вам также нужно иметь в виду эту проблему размера, поскольку это может привести к несовместимости данных между 32 и 64-битными версиями.

Кроме того, компилятор FreePascal с IDE Lazarus уже поддерживает 64-разрядную версию. Этот альтернативный компилятор Object Pascal не на 100% совместим с диалектом Borland/Codegear/Embarcadero Pascal, поэтому просто перекомпилировать его для 64-разрядного может быть не так просто, но это может помочь указать проблемы с 64-разрядными.

Ответ 3

Преобразование в 64 бит не должно быть очень болезненным. Начните с преднамеренного размера целого числа, где это имеет значение. Не используйте "integer" вместо Int32 для целых чисел размером 32 бита, а Int64 для целых чисел размером 64 бит. В последнем преобразовании бит определение Integer перешло от Int16 к Int32, поэтому вы играете в нем безопасно, указав точную глубину бит.

Если у вас есть встроенная сборка, создайте эквивалент pascal и создайте некоторые модульные тесты, чтобы гарантировать, что они работают одинаково. Выполните некоторые временные тесты и убедитесь, что сборка все еще работает достаточно быстро, чтобы сохранить. Если да, то вы захотите внести изменения в оба, как они нужны.

Ответ 4

Используйте NativeInt для целых чисел, которые могут содержать литые указатели.