На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Экспорт перегруженой функции через *.def файл
    Всем привет!
    В общем есть функция, перегруженная:

    ExpandedWrap disabled
      extern "C" __declspec(dllexport) UINT __stdcall Foo( MSIHANDLE handle )
      extern "C" __declspec(dllexport) UINT __stdcall Foo( MSIHANDLE handle, DWORD rid )


    Плюс ко всему она объявлена в *.def файле:
    ExpandedWrap disabled
      LIBRARY "SomeLibrary"
       
      EXPORTS
          Foo

    Естественно такой код генерирует варнинг что типа много раз пометили функцию как экспортируемую, уберите ее из def файла или уберите модификатор dllexport.
    Убрал модификаторы экспорта, получил:
    ExpandedWrap disabled
      UINT __stdcall Foo( MSIHANDLE handle )
      UINT __stdcall Foo( MSIHANDLE handle, DWORD rid )

    После чего летит ошибка:
    ExpandedWrap disabled
      1>SomeFile.def : warning LNK4022: cannot find unique match for symbol 'Foo'


    Почитал всякое, советуют убрать экспорт из *.def файла, и оставить extern "C" __declspec(dllexport) - но это не вариант! Потому как без def файла для x86 архитектуры функции экспортируются с декорированными именами, из за чего InstallShield их просто не видит.
    Почитал еще, предлагают в *.def файл запихнуть собственно две версии этой функции с перегрузкой, что то типа:

    ExpandedWrap disabled
      LIBRARY "SomeLibrary"
       
      EXPORTS
         ?Foo@@YAIK@Z
         ?Foo@@YAIKK@Z

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

    Теперь вопрос - как с помощью def файла экспортировать эти две функции? Возможно ли такое?

    Добавлено
    Да еще забыл сказать, перегруженная версия Foo с двумя параметрами, вызывается внутри Foo с одним параметром. И на сколько я понял - по сути экспортировать нужно одну версию:
    ExpandedWrap disabled
      UINT __stdcall Foo( MSIHANDLE handle )

    Конечно можно поменять имя второй функции. Но мне просто интересно стало - как без изменения имени экспортировать.

    Добавлено
    Так же что то начал тут экспериментировать. Еслиэти две функции заинлайнить, то ошибка пропадает. Может ли быть это ответом на мой вопрос?

    Добавлено
    Хм! Если экспортировать эти две функции, но при этом заинлайнить их, ошибки нет, в таблице экспорта:
    ExpandedWrap disabled
               19   12 000085A0 Foo

    Правильно ли я понимаю, что теперь при использовании будет использоваться та версия экспортируемой функции - которая была вызвана? Нет тут скрытых камней?
      В общем похоже с инлайн фигня получается. Похоже придется менять имя второй функции.
        KILLER, для перегруженных сущностей нужна декорация имён. Без вариантов. Если они при этом импортируются, то и в таблицах экспорта они должны проходить в декорированном виде.
        Как вариант, ты можешь заинлайнить – без их экспорта/импорта – простые переходники, которые будут вызывать по-разному обозванные функции. Что с ними будет делаться, уже неважно, можно и экспортировать, можно и явно линковать.
          Цитата Qraizer @
          KILLER, для перегруженных сущностей нужна декорация имён. Без вариантов. Если они при этом импортируются, то и в таблицах экспорта они должны проходить в декорированном виде.
          Как вариант, ты можешь заинлайнить – без их экспорта/импорта – простые переходники, которые будут вызывать по-разному обозванные функции. Что с ними будет делаться, уже неважно, можно и экспортировать, можно и явно линковать.

          Да в принципе меня больше интересовал вопрос с академической стороны, чем с практической.
          В принципе можно это решить, но не очень наверное переносимо получится, по крайней мере на мсдне пишут -> https://msdn.microsoft.com/en-us/library/s90k71yx.aspx
          Цитата
          To prevent this warning, specify the symbol in its decorated form. Run DUMPBIN on the object to see decorated names.

          Типа с помощью dumbin /export получить декорированное имя двух этих функций и запихнуть это в def файл. Я пробовал брать декорированное имя из ошибки линкера, для 64 битной конфигурации все отработало нормально, для конфигурации х86 не собралось.
          Потом подумал покумекал что могут мне эти инлайны дать, ведь в таблице экспорта должны быть две версии функции, иначе я не получу адрес нужной мне через какой нибудь GetProcAddress.
          В итоге вторую функцию просто переименовал.
          Если бы InstallShield понимал функции с декорированными именами, то я бы убрал def файл. А так, пришлось переименовать функцию ))
          Сообщение отредактировано: KILLER -
            В доке нашел абзац, может поможет:

            Цитата
            If you are exporting functions in a C++ file, you have to either place the decorated names in the .def file or define your exported functions with standard C linkage by using extern "C". If you need to place the decorated names in the .def file, you can obtain them by using the DUMPBIN tool or by using the linker /MAP option. Note that the decorated names produced by the compiler are compiler specific. If you place the decorated names produced by the Visual C++ compiler into a .def file, applications that link to your DLL must also be built using the same version of Visual C++ so that the decorated names in the calling application match the exported names in the DLL's .def file.
              Цитата KILLER @
              для 64 битной конфигурации все отработало нормально, для конфигурации х86 не собралось.
              Возможно декорирование для 64 и 32 бит различается. В таком случае, видимо, надо было в утилиту какой-то ключ дополнительно передать, чтобы он нужное декорированное имя выдал.

              А надёжнее в link /MAP добавить, в карте имена с использованным декорированием прописываются.

              Вообще, использовать DLL с экспортом декорированных имён часто неудобно. Поскольку использовать эти DLL можно (без дополнительных телодвижений) только с тем компилятором, которым они построены. Для последующего использования лучше пользоваться советом, который дал Qraizer
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0314 ]   [ 16 queries used ]   [ Generated: 19.03.24, 08:00 GMT ]