Сведения о вопросе

Oleksandr

21:04, 7th August, 2020

Теги

c++   c   dll    

Перегруженные функции в файле def C++ DLL

Просмотров: 557   Ответов: 6

Я пишу C/C++ DLL и хочу экспортировать определенные функции, которые я делал до использования файла .def, как это

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

например, с кодом, определенным следующим образом:

int Foo(int a);
void Bar(int foo);

Однако, что делать, если я хочу объявить перегруженный метод Foo() как:

int Foo(int a, int b);

Поскольку файл def имеет только имя функции, а не полный прототип, я не вижу, как он будет обрабатывать перегруженные функции. Вы просто используете одну запись и затем указываете, какая перегруженная версия вам нужна при передаче правильно прототипированного указателя функции на LoadLibrary() ?

Изменить: чтобы быть ясным, это на Windows с помощью Visual Studio 2005

Edit: пометил метод non-def (__declspec) как answer...I знаю, что это на самом деле не решает проблему с использованием def-файлов, как я хотел, но кажется, что, скорее всего, нет (официального) решения с использованием def-файлов. Однако оставим этот вопрос открытым, если кто-то знает что-то, что у нас нет перегруженных функций и def-файлов.



  Сведения об ответе

crush

07:53, 3rd August, 2020

Перегрузка функций - это функция C++, которая опирается на искажение имен (загадочные имена функций в сообщениях об ошибках компоновщика).

Записав искаженные имена в файл def, я могу связать и запустить свой тестовый проект:

LIBRARY "TestDLL"
EXPORTS
    ?Foo@@YAXH@Z
    ?Foo@@YAXHH@Z

кажется, работает на

void Foo( int x );
void Foo( int x, int y );

Поэтому скопируйте имена функций C++ из сообщения об ошибке и запишите их в свой def-файл. Однако реальный вопрос заключается в следующем: почему вы хотите использовать def-файл, а не использовать __declspec(dllexport) ?

Искореженные имена непереносимы, я тестировал с VC++ 2008.


  Сведения об ответе

DINO

09:59, 23rd August, 2020

В самом коде отметьте функции, которые вы хотите экспортировать с помощью _ _ declspec (dllexport). Например:

#define DllExport __declspec(dllexport)

int DllExport  Foo( int a ) {
  // implementation
}
int DllExport Foo( int a, int b ) {
  // implementation
}

В этом случае вам не нужно перечислять функции в файле .def.

Кроме того, вы можете использовать значение параметра по умолчанию, например:

int Foo( int a, int b = -1 )

Это предполагает, что существует значение для b, которое можно использовать, чтобы указать, что оно не используется. Если -1 является законным значением для b, или если нет или не должно быть дефолта, это не будет работать.

Edit (Adam Haile): исправлено использование __declspec как __dllspec не было правильным, поэтому я мог отметить это как официальное answer...it было достаточно близко.

Edit (Graeme): Ой - спасибо за исправление моей опечатки!


  Сведения об ответе

padenie

18:31, 4th August, 2020

У меня была похожая проблема, поэтому я хотел бы написать об этом также.

  1. Как правило, с использованием

    extern "C" __declspec(dllexport) void Foo();
    

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

  2. Если вы объявите функцию для использования __stdcall convention (как это делается для многих функций API), то

    extern "C" __declspec(dllexport) void __stdcall Foo();
    

    будет экспортировать искаженное имя, как _Foo@4. в этом случае может потребоваться явное сопоставление экспортированного имени к внутреннему искореженному имени.

О. как экспортировать незапутанное имя. В файле .def добавить

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

При этом будет предпринята попытка найти "best match" для внутренней функции Foo и экспортировать ее. В случае выше, где есть только один фу это создаст отображение

ФОО = _Foo@4

как можно увидеть через dumpbin /EXPORTS

Если вы перегрузили имя функции, то вам может потребоваться явно указать, какую функцию вы хотите в файле .def указав искаженное имя с помощью синтаксиса entryname[=internalname]. напр.

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

Б. Альтернативой .def файлам является то, что вы можете экспортировать имена "in place" с помощью #pragma.

#pragma comment(linker, "/export:Foo=_Foo@4")

C. Третий вариант-объявить только одну версию Foo как extern "C", подлежащую экспорту без путаницы. Подробности смотрите здесь .


  Сведения об ответе

LIZA

14:45, 10th August, 2020

Нет никакого официального способа сделать то, что вы хотите, потому что интерфейс dll-это C api.

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


  Сведения об ответе

qwerty101

20:27, 24th August, 2020

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

Это одна из причин, почему большинство функций WinXX имеют забавные имена, такие как *Ex или *2.


  Сведения об ответе

pumpa

15:21, 27th August, 2020

Который по определению является EXPORTS:

entryname[=internalname] [@ordinal [NONAME]] [PRIVATE] [DATA]

entryname - это имя функции или переменной, которую вы хотите экспортировать. Это необходимо. Если имя, которое вы экспортируете, отличается от имени в DLL, Укажите имя экспорта в DLL с помощью internalname.

Например, если ваш DLL экспортирует функцию func1() и вы хотите, чтобы она использовалась как func2(), вы должны указать:

EXPORTS
func2=func1

Просто посмотрите на искаженные имена (используя Dependency walker) и укажите свое собственное имя функций.

Источник: http://msdn.microsoft.com/en-us/library/hyx1zcd3(v=vs.71).aspx

Edit: это работает для dynamic DLLs, где нам нужно использовать GetProcAddress() для явного извлечения функций в Dll.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться