я могу смешать вызовы экспорта __cdecl с вызовами импорта __stdcall в DLL? - PullRequest
3 голосов
/ 02 августа 2011

пишу модуль для стороннего приложения;приложение uses __cdecl соглашение о вызовах.

В то же время у меня есть устаревшая DLL, в которой uses __stdcall соглашение о вызовах.

Могу ли я создать оболочку, которая на одном конце exports __cdecl функционирует, а на другом конце imports __stdcall функции?какие еще варианты у меня есть?

Спасибо,

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

Вот дополнительная информация, которая поможет мне прояснить мою ситуацию.

Существуетthird_party.exe, которым необходимо получить доступ к skeleton.dll.Исходный код skeleton.dll содержит заголовочный файл ниже и компилируется с использованием __cdecl.

#ifdef _EXPORTING
  #define DECLSPEC    __declspec(dllexport)
#else
   #define DECLSPEC    __declspec(dllimport)
#endif

#ifdef __cplusplus
   extern "C" {  
#endif

DECLSPEC int ICD_Create(char* id);
...
...
...

В идеале, я бы использовал исходный код скелета для разработки моей DLL;к сожалению, было бы слишком много времени переносить мой текущий унаследованный код VB6 в C ++.Учитывая это, мне пришлось взломать мой код VB6, следуя этому руководству (Это обходной путь, но он позволяет мне использовать ActiveX DLL в качестве стандартной C-библиотеки DLL).

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

Архитектура будет выглядеть следующим образом:

Application: ThirdParty.exe (out of your control: Uses __cdecl) 
     |
     |
Plugin module: Skeleton.dll (your code)
     |
     |
Legacy DLL: ModifiedVB6.dll (out of your control: Seem to work with __stdcall)

Унаследованная DLL генерируетdll, lib и def file;Нет заголовочного файла.

Ответы [ 2 ]

4 голосов
/ 02 августа 2011

DLL обычно поставляется с заголовочным файлом (.h) и связанной библиотекой импорта (.lib), которая имеет дело с соглашениями о вызовах, экспортированными прототипами функций и т. Д.

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

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


Перечитав ваш вопрос и ваш комментарий, я считаю, что у вас есть следующая архитектура:

Application (out of your control)
     |
     |
Plugin module (your code)
     |
     |
Legacy DLL (out of your control)

Старая DLL экспортирует свою функцию, используя __stdcall. Приложение импортирует функцию из плагина, используя __cdecl.

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

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


После обновления я подозреваю, что все ваши проблемы касаются того, как связать устаревшую DLL VB6 с вашей C ++ DLL. Поскольку у вас нет заголовочного файла (.h) для библиотеки VB6, вы, вероятно, пишете свои собственные переводы.

Если я правильно помню, VB6 поддерживает только __stdcall, который вы сейчас используете. Поэтому ваши проблемы, скорее всего, связаны с ошибочными переводами экспортированных функций VB в прототипы C ++.

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

Если вам нужна дополнительная помощь от переполнения стека, я думаю, вам нужно будет предоставить объявления функций VB6 и ваши попытки перевода, но я думаю, что это будет предметом нового вопроса (ов).

2 голосов
/ 02 августа 2011

__declspec(dllexport) требуется только для указания компилятору экспортировать идентификатор из DLL.Это не имеет никакого отношения к соглашению о вызовах функции, которую вы определяете (и, возможно, экспортируете), или функции, которую вы импортируете.Это должно быть указано отдельно, и __stdcall хорошо (но учтите, что функции vararg должны быть __cdecl, так как вызывающая сторона должна очистить стек).

Да, вы можете обернуть свою DLL другой DLLкоторый импортирует его и экспортирует функции, имеющие __cdecl соглашение о вызовах, но это может сбить с толку пользователей DLL.Я бы этого не делал, но это возможно.

...