Каков стандартный способ управления совместимостью соглашений о вызовах между программой и ее плагинами DLL? - PullRequest
0 голосов
/ 01 апреля 2020

Я создаю C программу, которая явно динамически загружает DLL как часть системы плагинов. Я использую G CC с MinGW на Windows 7.

Какое соглашение о вызовах должно использовать экспортируемые функции в DLL для того, чтобы быть максимально устойчивыми: успешно работать на разных Windows машины, выдерживающие разные версии компиляторов и т. д. c.

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

В настоящее время я только стремлюсь поддержать Windows (хотя ответы, относящиеся также к той же теме на Linux, также будут приветствоваться).

РЕДАКТИРОВАТЬ:

Пожалуйста, позвольте мне прояснить вопрос, как обсуждалось в разделе комментариев с @SS Anne.

Меня меньше беспокоит конкретное соглашение о вызовах. Меня больше беспокоит вопрос о том, что является стандартным способом обеспечения совместимости между двоичным файлом, созданным на компьютере X, и DLL (подключаемым модулем), созданным кем-то другим на компьютере Y, который может иметь другую ОС и т. Д. c.

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

Например, заголовок api.h, предоставляемый разработчикам плагина, определяет #define CALL __cdecl. И после выполнения #include "api.h" экспортируемые функции в DLL плагина объявляются так: void CALL func(void);.

Используется ли это решение на практике? Есть ли разные подходы?

1 Ответ

0 голосов
/ 14 апреля 2020

Редактировать следующий вопрос edit

Нет, вам не нужно "обеспечивать совместимость между двоичным файлом, созданным на компьютере X, и DLL (плагином), созданным кем-то другим на машине Y, что может иметь другую ОС и т. д. c ", кроме случаев, когда ОС, для которой был создан двоичный X, полностью отличается от ОС, на которой был построен двоичный Y. Для контекста, это список операционных систем, которые не совместимы друг с другом:

  • Windows
  • Linux
  • Ma c
  • BSD

Вам не нужно указывать соглашение о вызовах вручную. Вам даже не нужно думать о любых соглашениях о вызовах.

Ваше решение не используется на практике. Требуется другой подход: не делать ничего .

Оригинальный ответ

Для x86_64 Windows стандартное соглашение о вызовах Microsoft x64 ABI - это то, что используется по всем направлениям. Это должно быть включено по умолчанию.

Для x86 Windows изображение немного мутнее: большинство Windows вызовов API используют __stdcall, но __cdecl является соглашением по умолчанию для пользовательских функций , Разница между ними заключается в том, что в первом вызываемый абонент очищает стек, а во втором вызывающий очищает стек.

В этом случае я бы go с __cdecl, как это по умолчанию для MSVC ++ и G CC для таргетинга Windows.

См. __cdecl или __stdcall для Windows? для получения дополнительной информации об этом.

На Linux вы всегда должны go с соглашением о вызовах по умолчанию для вашей архитектуры. Эта опция всегда самая переносимая.

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

...