Здравствуйте, icWasya, Вы писали: W>Используй def — файл
Я же экспортирую функции, используя __declspec(dllexport), а не def-файл. Соответственно и вопрос у меня не связан с def-файлом... Мне важно понять причину, почему так происходит.
Здравствуйте, Loerosim, Вы писали:
L>Я же экспортирую функции, используя __declspec(dllexport), а не def-файл. Соответственно и вопрос у меня не связан с def-файлом... Мне важно понять причину, почему так происходит.
Посмотри PE вьювером (или просто в текстовом редакторе), какое имя функции получилось в DLL.
Здравствуйте, что, Вы писали:
что>Здравствуйте, Loerosim, Вы писали:
L>>Я же экспортирую функции, используя __declspec(dllexport), а не def-файл. Соответственно и вопрос у меня не связан с def-файлом... Мне важно понять причину, почему так происходит. что>Посмотри PE вьювером (или просто в текстовом редакторе), какое имя функции получилось в DLL.
Dumpbin'ом увидел, что добавляя __stdcall, получаю имя функции с окончанием @0.
Тогда как при создании dll задавать соглашения вызовов?
Здравствуйте, Loerosim, Вы писали:
L>Здравствуйте, что, Вы писали:
что>>Здравствуйте, Loerosim, Вы писали:
L>>>Я же экспортирую функции, используя __declspec(dllexport), а не def-файл. Соответственно и вопрос у меня не связан с def-файлом... Мне важно понять причину, почему так происходит. что>>Посмотри PE вьювером (или просто в текстовом редакторе), какое имя функции получилось в DLL. L>Dumpbin'ом увидел, что добавляя __stdcall, получаю имя функции с окончанием @0. L>Тогда как при создании dll задавать соглашения вызовов?
Так тебе «важно понять причину», «задавать соглашения вызовов» или «экспортировать функцию с нужным именем» ?
L>Если же убрать __stdcall, то всё будет хорошо...
Дело в том, что компилятор [VC++], чтобы отличать одну функцию от другой, — а C++ допускает
такую перегрузку, — хранит все имена в специальном внутреннем формате. Это называется декорацией
имен (name decoration или name mangling). Декорированное имя формируется в зависимости от имени функции,
от количества и типов ее аргументов, от типа соглашения о выховах (stdcall/cdecl/fastcall), а также от
того, используется ли C или C++.
Кое-какая полезная информация здесь — http://msdn.microsoft.com/en-us/library/deaxefa7(v=vs.100).aspx
До тех пор, пока функция не экспортируется, эта особенность нас не беспокоит, так как все вопросы
"стыковки" решаются компилятором. При экспорте функции, в зависимости от того, какой был выбран
способ экспорта, — def-файл или __declspec(dllexport), — в секцию экспорта попадает либо ее
оригинальное имя, либо уже декорированное. В первом случае GetProcAddress сможет найти функцию по
ее оригинальному имени, во втором — нет.
Тут еще вот какая особенность — функция C (не C++), имеющая соглашение о вызовах cdecl,
при экспорте будет иметь декорированное имя, совпадающее с оригинальным, и поэтому ее можно будет
находить посредством GetProcAddress, вне зависимости от типа экспорта. А компилятор VC++, если не
указано иное, считает все функции объявленными с соглашением cdecl. Как раз Ваш случай.
Здравствуйте, icWasya, Вы писали: W>Так тебе «важно понять причину», «задавать соглашения вызовов» или «экспортировать функцию с нужным именем» ?
Мне всё важно. =)
Теперь вот я осознал, что Ваш намек про def файл был правильным путем решения моей проблемы. Принцип "на любой вопрос даю любой ответ" имеет место быть, но всё же для новичка не всегда очевидны сухие ответы без пояснения.
Здравствуйте, okman, Вы писали:
O>такую перегрузку, — хранит все имена в специальном внутреннем формате. Это называется декорацией O>имен (name decoration или name mangling).
Спасибо большое за пояснения и за ссылки, буду разбираться!
А про name mangling я читал и даже встречался при вызове С++ кода из C файла. Но решение было extern "C". В dll функция я такое прописал, но имена все равно обернулись...
Здравствуйте, Loerosim, Вы писали:
L>Dumpbin'ом увидел, что добавляя __stdcall, получаю имя функции с окончанием @0. L>Тогда как при создании dll задавать соглашения вызовов?
Используй DEF файл
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, okman, Вы писали:
O>Дело в том, что компилятор [VC++], чтобы отличать одну функцию от другой, — а C++ допускает O>такую перегрузку, — хранит все имена в специальном внутреннем формате. Это называется декорацией O>имен (name decoration или name mangling). Декорированное имя формируется в зависимости от имени функции, O>от количества и типов ее аргументов, от типа соглашения о выховах (stdcall/cdecl/fastcall), а также от O>того, используется ли C или C++. O>Кое-какая полезная информация здесь — http://msdn.microsoft.com/en-us/library/deaxefa7(v=vs.100).aspx
Для extern "C" функции перегрузка недоступна, так что причина декорирования имён другая -- совместимость с тем, как это было принято делать в С.
А в С так принято было делать из соображений надёжности. Что бы тип декорирования имения, гарантировал тип соглашения о вызове...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали: E>Для extern "C" функции перегрузка недоступна, так что причина декорирования имён другая -- совместимость с тем, как это было принято делать в С. E>А в С так принято было делать из соображений надёжности. Что бы тип декорирования имения, гарантировал тип соглашения о вызове...
И Вам спасибо за ответ. =) Я поработал с гуглом и просветился, что extern "C" защищает от name mangling, но при объявлении соглашений вызова уже имеет место быть decorations. Всё решил просто — через __cdecl, что по умолчанию. Иначе, как мне сразу подсказали, нужен def-файл.
PS: Странно, что dot-net C# загружал функции и работал с ними без проблем не зависимо от объявленного соглашения вызовов. А проблему удалось установить только при отладке в C++ проекте.
Здравствуйте, Loerosim, Вы писали:
L>PS: Странно, что dot-net C# загружал функции и работал с ними без проблем не зависимо от объявленного соглашения вызовов.
Ну он просто и так и сяк пробует искать, за одно и соглашение о вызове выясняет
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Loerosim, Вы писали:
L>PS: Странно, что dot-net C# загружал функции и работал с ними без проблем не зависимо от объявленного соглашения вызовов. А проблему удалось установить только при отладке в C++ проекте.
Рискну предположить, что C# код использовал тот же манглинг (кстати, во времена древних компилеров манглинг был manufacturer-specific), либо загружал функцию по ординалу
Все, что ответили про декорацию — верно. Могу лишь посоветовать еще запускать dumpbin с ключом /EXPORTS, увидишь, по какому имени функция экспортируется, после чего возьми это имя (как бы оно тебя ни пугало) и используй в GetProcAddress