Перегруженные функции в файле определения DLL C++

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

LIBRARY "MyLib"
EXPORTS
  Foo
  Bar

с кодом, определенным как это, например:

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

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

int Foo(int a, int b);

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

Править: Чтобы быть ясным, это находится в Windows с помощью Visual Studio 2005

Править: Отмеченный неопределение (__ declspec) метод как ответ... Я знаю, что это на самом деле не решает проблему с помощью файлов определения, как я хотел, но кажется, что там не вероятно никакое (официальное) решение с помощью файлов определения. Оставит вопрос открытым, однако, в случае, если кто-то знает что-то, что у нас нет файлов определения и перегруженных функций.

9
задан Adam Haile 25 August 2008 в 14:56
поделиться

5 ответов

В самом коде отметьте функции, Вы хотите экспортировать использование __ 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, или если не будет или не должно будет быть значением по умолчанию, то это не будет работать.

Редактирование (Adam Haile): Исправленный для использования __ declspec в качестве __ dllspec не был корректен, таким образом, я мог отметить это как официальный ответ... это было достаточно близко.

Редактирование (Graeme): ой - благодарит исправить мою опечатку!

9
ответ дан 4 December 2019 в 06:42
поделиться

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

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

3
ответ дан 4 December 2019 в 06:42
поделиться

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

Путем записи скорректированных имен в файл определения я могу получить свой тестовый проект связаться и работать:

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

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

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

Так скопируйте имена функций C++ с сообщения об ошибке и запишите им в Ваш файл определения. Однако реальный вопрос: Почему Вы хотите использовать файл определения и не пойти с __ declspec (dllexport)?

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

11
ответ дан 4 December 2019 в 06:42
поделиться

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

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

2
ответ дан 4 December 2019 в 06:42
поделиться

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

  1. Обычно использование

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

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

  2. Если Вы объявляете, что функция использует __ stdcall конвенция (как сделан для многих API-функций), затем

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

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

A. Как экспортировать неискаженное имя. В .def файле добавляют

----
EXPORTS
    ; Explicit exports can go here

    Foo
-----

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

Нечто = _Foo@4

как может быть, посмотрите через dumpbin / ЭКСПОРТ

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

----
EXPORTS
    ; Explicit exports can go here

    Foo=_Foo@4
-----

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

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

C. Третья альтернатива должна объявить всего, что одна версия Foo как экстерн "C" экспортируется неискаженная. Посмотрите здесь для деталей.

8
ответ дан 4 December 2019 в 06:42
поделиться