Мне нужен простой пример экспорта функции из C ++ DLL Windows.
Я хотел бы увидеть заголовок, .cpp
файл и .def
файл (если это абсолютно необходимо).
Я бы хотел, чтобы экспортируемое имя не было украшено . Я хотел бы использовать самое стандартное соглашение о вызовах ( __stdcall
?). Я бы хотел использовать __declspec(dllexport)
и не использовать .def
файл.
Например:
//header
extern "C"
{
__declspec(dllexport) int __stdcall foo(long bar);
}
//cpp
int __stdcall foo(long bar)
{
return 0;
}
Я пытаюсь не допустить, чтобы компоновщик добавил к имени символы подчеркивания и / или числа (количество байтов?).
Я нормально не поддерживаю dllimport
и не dllexport
использую тот же заголовок. Мне не нужна информация об экспорте методов класса C ++, только глобальные функции в стиле c.
ОБНОВИТЬ
Исключение соглашения о вызовах (и использовании extern "C"
) дает мне имена экспорта, которые мне нравятся, но что это значит? Независимо от соглашения о вызовах по умолчанию, которое я получаю, pinvoke (.NET), declare (vb6) и ожидаемый GetProcAddress
? (Я думаю, GetProcAddress
это будет зависеть от указателя функции, созданного вызывающим).
Я хочу, чтобы эта DLL использовалась без файла заголовка, поэтому мне действительно не нужно много фантазий, #defines
чтобы сделать заголовок пригодным для использования вызывающим.
Я согласен с тем, что мне нужно использовать *.def
файл.
источник
extern C
удалит украшение, которое описывает типы параметров функции, но не украшение, которое описывает соглашение о вызове функции; б) чтобы удалить все декорации, вам необходимо указать (недекорированное) имя в файле DEF.Ответы:
Если вам нужен простой экспорт на C, используйте проект C, а не C ++. Библиотеки DLL C ++ полагаются на изменение имен для всех измов C ++ (пространства имен и т. Д.). Вы можете скомпилировать свой код как C, зайдя в настройки вашего проекта в C / C ++ -> Advanced, там есть опция «Compile As», которая соответствует переключателям компилятора / TP и / TC.
Если вы по-прежнему хотите использовать C ++ для написания внутренней части вашей библиотеки, но экспортировать некоторые функции без привязки для использования вне C ++, см. Второй раздел ниже.
Экспорт / импорт библиотек DLL в VC ++
На самом деле вам нужно определить условный макрос в заголовке, который будет включен во все исходные файлы в вашем проекте DLL:
Затем для функции, которую вы хотите экспортировать, вы используете
LIBRARY_API
:В проекте сборки библиотеки создайте определение,
LIBRARY_EXPORTS
это приведет к тому, что ваши функции будут экспортированы для сборки DLL.Поскольку
LIBRARY_EXPORTS
не будет определен в проекте, использующем DLL, когда этот проект включает файл заголовка вашей библиотеки, вместо этого будут импортированы все функции.Если ваша библиотека должна быть кросс-платформенной, вы можете определить LIBRARY_API как ничто, если не в Windows:
При использовании dllexport / dllimport вам не нужно использовать файлы DEF, если вы используете файлы DEF, вам не нужно использовать dllexport / dllimport. Эти два метода решают одну и ту же задачу разными способами, я считаю, что dllexport / dllimport - это рекомендуемый метод из двух.
Экспорт несвязанных функций из библиотеки DLL C ++ для LoadLibrary / PInvoke
Если вам нужно использовать LoadLibrary и GetProcAddress или, возможно, импортировать с другого языка (например, PInvoke из .NET или FFI в Python / R и т. Д.), Вы можете использовать
extern "C"
встроенный с вашим dllexport, чтобы сообщить компилятору C ++ не искажать имена. И поскольку мы используем GetProcAddress вместо dllimport, нам не нужно выполнять танец ifdef сверху, просто простой dllexport:Код:
А вот как выглядит экспорт с помощью Dumpbin / exports:
Итак, этот код отлично работает:
источник
Для C ++:
Я только что столкнулся с той же проблемой, и я думаю, что стоит упомянуть, что проблема возникает, когда вы используете оба
__stdcall
(илиWINAPI
) иextern "C"
:Как известно
extern "C"
убирает украшение так, чтобы вместо:вы получите имя символа без украшений:
Однако
_stdcall
(= макрос WINAPI, который изменяет соглашение о вызовах) также украшает имена, так что, если мы используем оба, мы получаем:и преимущество
extern "C"
теряется, потому что символ украшен (_ @bytes)Это особенно сложно, если вы ориентируетесь как на платформы x86, так и на x64.
Два решения
Используйте файл определения. Но это заставляет вас поддерживать состояние файла def.
Самый простой способ: определить макрос (см. msdn ):
а затем включите следующую прагму в тело функции:
Полный пример:
Это экспортирует функцию без декорирования для целей x86 и x64 с сохранением
__stdcall
соглашения для x86. В этом случае__declspec(dllexport)
не требуется.источник
__FUNCTION__
макрос работает только в функциях.У меня была точно такая же проблема, моим решением было использование файла определения модуля (.def) вместо
__declspec(dllexport)
определения экспорта ( http://msdn.microsoft.com/en-us/library/d91k01sh.aspx ). Понятия не имею, почему это работает, но работаетисточник
.def
файла экспорта модуля действительно работает, но за счет возможности предоставитьextern
определения в файле заголовка, например, для глобальных данных - в этом случае вы должны предоставитьextern
определение вручную при внутреннем использовании эти данные. (Да, бывают случаи, когда вам это нужно.) Как в целом, так и особенно для кроссплатформенного кода, лучше просто использовать__declspec()
макрос, чтобы вы могли нормально передавать данные.__stdcall
, то украшения снимать не__declspec(dllexport)
будешь . Однако добавление функции к завещанию..def
Я думаю, что _naked может получить то, что вы хотите, но он также не позволяет компилятору генерировать код управления стеком для функции. extern «C» вызывает оформление имени в стиле C. Удалите это, и это должно избавить вас от ваших _. Компоновщик не добавляет подчеркивания, а компилятор. stdcall вызывает добавление размера стека аргументов.
Для получения дополнительной информации см. Http://en.wikipedia.org/wiki/X86_calling_conventions http://www.codeproject.com/KB/cpp/calling_conventions_demystified.aspx.
Более важный вопрос - почему вы хотите это сделать? Что не так с искореженными именами?
источник