|
|
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
Вопросов на эту тему было уйма. Моя трабла - то же самое, вид сбоку. Если у кого есть этот момент - вникните, плиз. VC98 Два проекта Dll + вызывающее консольное приложение. 1. Если в dll объявлять экспортируемую функцию func как __cdecl и посмотреть затем в мап-фале - называться она будет _func, но GetProcAddress в вызывающем приложении работает с именем "func". Все счастливы. 2. Если экспортируемую функцию объявить как __stdcall, то в мапфайле ее обнаруживаешь как _func@x, где x размер аргументов в байтах. Соответственно, GetProcAddress работает по этому кривому имени, например _func@8 3.Соответственно, если _cdecl функцию пытаться вызвать по __stdcall указателю получим эксцепшн. Возникла идея проверить как оно работает с виндовыми длл-лями. Понять как определены функции в том же kernel32.dll - не могу в студии есть хедеры только для либов (другие и не нужны).Однако радость в том, что как ни описывай указатель на получаемую через GetProcAddress (указатель на) функцию - хоть __stdcall, хоть __cdecl - никаких эксцепшенов нет и все работает (проверял). Для последнего случая, возможно, компилятор молча устраняет ошибку (бред, но ничего другого в голову не пришло). К вопросу, зачем все эти пляски с бубном. Дело в том, что консольное приложение служит исколючительно для тестирования, а работать с ДЛЛ придется из некоего рантайма, где, впроде как, функции из DLL импортируются будучи _stdcall. Поэтому перспектива получать адрес длл-ой функции по имени _func@8 - не очень впечатляет. И еще вопрос - __stdcall, WINAPI, PASCAL соглашения не есть ли одно и то же? Буду признателен, если ткнете носом в доку. Айл би бэк. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2006, 11:57 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800 [поскипано] Дело в том, что консольное приложение служит исколючительно для тестирования, а работать с ДЛЛ придется из некоего рантайма, где, впроде как, функции из DLL импортируются будучи _stdcall. Поэтому перспектива получать адрес длл-ой функции по имени _func@8 - не очень впечатляет. [поскипано] Я, например, для этого в VS пишу def-файл, в котором указываю, какие имена надо оставлять в человеческом виде. Код: plaintext 1. 2. 3. 4. 5. собаканомер - необязательно. На сколько я понимаю, это только для того, чтобы функции можно было искать по номеру. Надеюсь, вопрос заключался в этом. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2006, 12:23 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
Нет, не в этом. Вопрос о справедливости - ибо не верится мне, что так и задумано было - звать _hhh@8 - это есть неверный путь. Сдается мне, что я просто что-то не учел. С помощью деф-файла уверен, что можно, но 1. Не делал и не пробовал и (поправьте меня, если я не заметил) в студии это не есть стандартный тул - т.е. подразумевается возможность нормальной работы и без них. А вот, не получается. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2006, 13:19 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800Нет, не в этом. Вопрос о справедливости - ибо не верится мне, что так и задумано было - звать _hhh@8 - это есть неверный путь. Сдается мне, что я просто что-то не учел. С помощью деф-файла уверен, что можно, но 1. Не делал и не пробовал и (поправьте меня, если я не заметил) в студии это не есть стандартный тул - т.е. подразумевается возможность нормальной работы и без них. А вот, не получается. 1) если Вы грузите дэлеле ЯВНО, то Вы должны правильно указывать имя которое Вы ищите в модуле. 2) если Вы грузите НЕ ЯВНО, то для этих целей служит ашничек и либ файл, который в принцепе и делает связывание имён при загрузке (не обязательно) Вашего экзешничка. В данном случае экспортируемое-импортируемое имя до фонаря и чтоб не налететь на конфликт имён компилятор генерит бла-бла-бла-собака-имя типа того... 3) деф файл - стандартный способ указания ЯВНЫХ имён ЯВНЫМ функциям-классам-переменным...пример выше был приведён корректно и описывал этот подход. 4) В добавок при описании вашего экспорта-импорта декларируется правило работы с передаваемыми параметрами (кто чистит вызывающий или вызываемая, в случае с функциями и методами)... с уважением (круглый) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2006, 16:13 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
2) если Вы грузите НЕ ЯВНО, то для этих целей служит ашничек и либ файл, который в принцепе и делает связывание имён при загрузке (не обязательно) Вашего экзешничка. В данном случае экспортируемое-импортируемое имя до фонаря и чтоб не налететь на конфликт имён компилятор генерит бла-бла-бла-собака-имя типа того... Не интересно. Вопрос не про это. По-моему по первому посту было ясно, что явная загрузка. 3) деф файл - стандартный способ указания ЯВНЫХ имён ЯВНЫМ функциям-классам-переменным...пример выше был приведён корректно и описывал этот подход. (круглый) Где в 98 студии работа с дефами? И, вообще, это немного в сторону. 4) В добавок при описании вашего экспорта-импорта декларируется правило работы с передаваемыми параметрами (кто чистит вызывающий или вызываемая, в случае с функциями и методами)... Повторю вопрос. Студия умеет собирать ДЛЛ без дефов (или же делает вид, что без дефов). Не суть - требуется только сурс и ключик компайлера. Однако же, при явной загрузке получаемой ДЛЛ получить указатель на экспортную функцию для ее варианта не __cdecl по ее указаному имени не получается. Приходится использовать кривые имена, что для меня означает одно - что я что-то криво сделал на этапе сборки длл. Однако, что же? В качестве отдельного размышления - привел пример явной загрузки функций из стандартных виндовых длл - оказывается пофигу, какой тип соглашения указать для указателя. Что, по меньшей мере, странно. И, кажется, все это я уже писал выше. Вам, коллега, спасибо за участие. Но, к сожалению, ответ несколько не туда. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2006, 20:00 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800что я что-то криво сделал на этапе сборки длл. Однако, что же? Не использовал def-файл при сборке dll. T800В качестве отдельного размышления - привел пример явной загрузки функций из стандартных виндовых длл - оказывается пофигу, какой тип соглашения указать для указателя. Что, по меньшей мере, странно.Ничего странного. Эта информация (stdcall или cdecl) сохраняется в библиотеке при создании dll. И при явном подключении dll к проекту используется. В одной dll могут быть функции с любым принципом вызова и до тех пор пока вызывающая программа их знает - они будут прекрасно работать. А ответ по первому вопросу: использовать def файл при создании dll. Все проблемы решаться мгновенно. И к чертям что думает о "стандартности" defов VC98. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.07.2006, 21:45 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
White Owl T800что я что-то криво сделал на этапе сборки длл. Однако, что же? Не использовал def-файл при сборке dll. Сенкс. Однако, не понял ваши слова по поводу стандартных виндовых длл. Если функция описана как __cdecl, то при использовании указателя __stdcall - я вылечу с ошибкой, и вайс верса. Смущает меня (как в свое время древнего человека молния) то, что для одно и той же (подчеркиваю - одной и той же) функции из, например kernel32.dll можно использовать для хранения адреса указатели для разных типов соглашений. Поясните, пожалуйста. Спасибо ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 13:01 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
[quot T800]Не интересно. Вопрос не про это. По-моему по первому посту было ясно, что явная загрузка. [/quot ] Из Вашего поста лично мне показалось, что Вы не до конца понимаете происходящее... [quot T800]Где в 98 студии работа с дефами?[/quot ] Может подвести память, но на дереве проджекта правая клавиша крыски и добавить новый файл (искать Module-Definition file). Даже в последних студиях не убрали - что косвенно подтверждает СТАНДАРТИЗАЦИЮ данного подхода. [quot T800]Повторю вопрос. Студия умеет собирать ДЛЛ без дефов (или же делает вид, что без дефов). Не суть - требуется только сурс и ключик компайлера. Однако же, при явной загрузке получаемой ДЛЛ получить указатель на экспортную функцию для ее варианта не __cdecl по ее указаному имени не получается. Приходится использовать кривые имена, что для меня означает одно - что я что-то криво сделал на этапе сборки длл. Однако, что же? [/quot ] ответ уже прозвучал помоему. достаточно обьявить о порядке вызова данной функции. [quot T800]В качестве отдельного размышления - привел пример явной загрузки функций из стандартных виндовых длл - оказывается пофигу, какой тип соглашения указать для указателя. Что, по меньшей мере, странно.[/quot ] это всё только кажеться... укажите другой порядок очистки стэка вызываемой функции и привет семье обспечен... с уважением (круглый) ЗЫ Может на кошки (примеры) перейдём ? Что не ясно, что не работает? Чего хочеться ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 16:36 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
На данный момент стандартные соглашения на экспортируемые функции в Win32 - это __stdcall. Его надо использовать. WINAPI, PASCAL - это макросы, которые преобразуются в нужный модификатор, указывающий на соглашения о вызовах функции. WINAPI ==> __stdcall PASCAL ==> __pascal (или __fortran) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:28 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
Летсгоу. Из Вашего поста лично мне показалось, что Вы не до конца понимаете происходящее... Ну, раз так выглядит со стороны.. T800Где в 98 студии работа с дефами?[/quot ] [quot]Может подвести память, но на дереве проджекта правая клавиша крыски и добавить новый файл (искать Module-Definition file). Даже в последних студиях не убрали - что косвенно подтверждает СТАНДАРТИЗАЦИЮ данного подхода. Ну, там есть вообще *.* маска :) Проблема не в том, чтобы деф добавить, вопрос о том, что деф инструмент, как минимум необязательный.. Только, вот, как показывает практика - без него не работает. Ну и студия, например при создании ДЛЛ проекта про деф молчит. При создании симпл длл проекта дефа нет. Т.е. я расценил это как предложение работать без оного. ответ уже прозвучал помоему. достаточно обьявить о порядке вызова данной функции. В дефе? В оригинале, (ну, раз мой великий и могучий подвел и все было непонятно) меня интересовал вопрос, возможно ли (без использования дефов) с помощью VС написать длл и явно ее грузить и вызывать функции по имени, при условии, что экспортируемые функции длл определены как __stdcall? Если вы скажете: "Брателло, ты че, не знаешь, что если в длл экспортируется __stdcall функция, то при явной загрузке библиотеки можно только или звать ее по кривому имени либо юзать деф-файл. И это нормально." - я пойму. Но никто так не сказал. Я не понимаю, почему, если я объявляю функцию как __cdecl никакой деф нах не нужен. Но если как __stdcall - то обязательно. Или это стандарт такой? Я просто не знаю. Вот и спрашиваю - почему __cdecl работает а __stdcall - нет. Если дэф нужен обязательно, почему при экспорте __cdecl функций и без него все хорошо? Прочитал (то, что выше). Тоже не по-русски. Надеюсь, переведете. это всё только кажеться... укажите другой порядок очистки стэка вызываемой функции и привет семье обспечен... Этот вопрос снимаю с повестки, ибо, написав очередной пример, вылетел, дернув kernel32.dll FreeLibrary через __cdecl указатель (чему обрадовался, ибо так быть и должно).. Посмотрю еще разик на других функциях. Странно, если приглючилось. С другой стороны - пусть лучше это меня плющит, чем окажется, что все - матрица. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:30 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800 ибо не верится мне, что так и задумано было - звать _hhh@8 - это есть неверный путь. Сдается мне, что я просто что-то не учел. Так и задумано. Есть имя функции в словаре глобальных ссылок. Это одно имя. И есть имя функции в словаре импорта и в словаре экспорта. Это второе имя. Эти имена в принципе разные, они не обязаны совпадать. Второго имени вообще может не быть, можно производить импорт и экспорт по номерам. Можно и по номерам, и по именам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:31 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
1) если Вы грузите дэлеле ЯВНО, то Вы должны правильно указывать имя которое Вы ищите в модуле. В этом случае используется имя экспорта или номер экспорта. 2) если Вы грузите НЕ ЯВНО, то для этих целей служит ашничек и либ файл, который в принцепе и делает связывание имён при загрузке (не обязательно) Вашего экзешничка. В данном случае экспортируемое-импортируемое имя до фонаря и чтоб не налететь на конфликт имён компилятор генерит бла-бла-бла-собака-имя типа того... Правильно, потому что внутри собираемой программы используется имя в словаре внешних ссылок линкера. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:33 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
MasterZivНа данный момент стандартные соглашения на экспортируемые функции в Win32 - это __stdcall. Его надо использовать. WINAPI, PASCAL - это макросы, которые преобразуются в нужный модификатор, указывающий на соглашения о вызовах функции. WINAPI ==> __stdcall PASCAL ==> __pascal (или __fortran) Вот если бы не встретил во всякого рода бумажках фразу, что стандартное соглашение для апишных функций - PASCAL ... __stdcall == WINAPI == PASCAL Вот что пишут люди. Они правы? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:34 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800 MasterZiv Вот если бы не встретил во всякого рода бумажках фразу, что стандартное соглашение для апишных функций - PASCAL ... [quot ]__stdcall == WINAPI == PASCAL Вот что пишут люди. Они правы? Это было давно, в WIN16. Сейчас, в Win32 , -- __stdcall ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:36 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
MasterZiv T800 ибо не верится мне, что так и задумано было - звать _hhh@8 - это есть неверный путь. Сдается мне, что я просто что-то не учел. Так и задумано. Есть имя функции в словаре глобальных ссылок. Это одно имя. И есть имя функции в словаре импорта и в словаре экспорта. Это второе имя. Эти имена в принципе разные, они не обязаны совпадать. Второго имени вообще может не быть, можно производить импорт и экспорт по номерам. Можно и по номерам, и по именам. Тогда получается, что товарищи из МАГАКОРПОРАЦИИ предусмотрели, что при сборке DLL для cdecl функции имя в словаре импорта будет таким же, как я определил в коде, а для остальных - как получится. Так? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:38 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
MasterZiv T800 MasterZiv Вот если бы не встретил во всякого рода бумажках фразу, что стандартное соглашение для апишных функций - PASCAL ... [quot ]__stdcall == WINAPI == PASCAL Вот что пишут люди. Они правы? Это было давно, в WIN16. Сейчас, в Win32 , -- __stdcall 1. Тогда надо подробнее. Соглашения о вызовах для Win16 и 32 отличаются, т.е. Win16 stdcall не есть Win32 stdcall. За тупость простите, но это так? 2. Win32 PASCAL соглашение - само по себе - оно не Win32 stdcall. Оба существуют параллельно. Так? Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 18:44 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800Тогда получается, что товарищи из МАГАКОРПОРАЦИИ предусмотрели, что при сборке DLL для cdecl функции имя в словаре импорта будет таким же, как я определил в коде, а для остальных - как получится. Так?Да. Вот пример: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Теперь можешь поиграться с dll'кой: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. Потом можешь убрать из исходника CryptBy.c слова __declspec(dllexport) , сделать вот такой CryptBy.def: Код: plaintext 1. 2. 3. 4. Все вопросы отпадут :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 19:01 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T8001. Тогда надо подробнее. Соглашения о вызовах для Win16 и 32 отличаются, т.е. Win16 stdcall не есть Win32 stdcall. За тупость простите, но это так?На самом деле разницы нет :) В обоих случаях это все идет через препроцессор до базового stdcall. Просто во времена MS-DOS и Win16 программы написаные на С обычно использовали соглашение в последствии названое cdecl а программы написаные на pascal (в частности Turbo Pascal) использовали соглашение в последствии названое stdcall. Создатели виндов решили что паскалевский тип вызова удобнее для dll и использовали его. Потому он и называется stdcall (Standard Calling Convention) а обратное соглашение использованое в C - стало соответственно cdecl (C Declaration). T8002. Win32 PASCAL соглашение - само по себе - оно не Win32 stdcall. Оба существуют параллельно. Так?И да и нет. Ты действительно можешь независимо использовать PASCAL или stdcall модификаторы при объявлении функций. Но при компиляции они оба превратятся в одно и тоже. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 19:10 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
И да и нет. Ты действительно можешь независимо использовать PASCAL или stdcall модификаторы при объявлении функций. Но при компиляции они оба превратятся в одно и тоже. Не, ну тогда вы меня просто запутали предыдущим постом. А утверждение WINAPI=PASCAL=__stdcall верно. Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 19:37 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
White Owl T800Тогда получается, что товарищи из МАГАКОРПОРАЦИИ предусмотрели, что при сборке DLL для cdecl функции имя в словаре импорта будет таким же, как я определил в коде, а для остальных - как получится. Так?Да. странная логика, однако.. это, наверное, у них религиозные предпочтения. А с дрегими компайлерам, борландовским, например та же фигня? Или вы не пробовали, в силу того, что собираете только с дефами? получаешь в CryptBy.dll два экспортируемых имени CryptByAA и _CryptBy55@4 Кстати. Как я понял, в мап-файле указаны экспортируемые имена. Так для _cdecl функций перед именем стоит андерско, но указатель GetProcAddress возвращает по имени без оного. Кроме того, в дельфевском (или басиковском) форуме я видел, что людям приходится звать _cdecl функции в виде _fname.. Так что, похоже, здесь нам помогает невидима рука Билли-Воротчика. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 19:48 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800WINAPI=PASCAL=__stdcall верно. Идем в windef.h и видим там такой кусок: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 20:01 |
|
||
|
One moment, please
|
|||
|---|---|---|---|
|
#18+
T800А с дрегими компайлерам, борландовским, например та же фигня? Или вы не пробовали, в силу того, что собираете только с дефами?Ну в общем да, я предпочитаю пользоваться def-ами, жить с ними проще :) Но вот тот же самый CryptBy.c собраный Борландом командой bcc32 -tWD CryptBy.c. Дал в итоговой dll имена _CryptByAA и CryptBy55. Обрати внимание, что BC сделал все наоборот! И не добавил в имя "@4" как это делал VC :) T800Кстати. Как я понял, в мап-файле указаны экспортируемые имена.Нет, это не экспортируемые, это внутренние имена. Там перечисляются имена в том написании в котором они хранятся в объектных файлах. При линковке dll эти имена могут быть заменены на те которые указаны в def файле, но в map останутся внутренние имена из объектников. T800Кроме того, в дельфевском (или басиковском) форуме я видел, что людям приходится звать _cdecl функции в виде _fname.. Это только для криво собранных dll. "Криво" означает для dll у которых при создании не использовались def-файлы и переопределение экспортируемых имен :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 18.07.2006, 20:13 |
|
||
|
|

start [/forum/topic.php?fid=57&fpage=343&tid=2030828]: |
0ms |
get settings: |
7ms |
get forum list: |
12ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
42ms |
get topic data: |
6ms |
get forum data: |
1ms |
get page messages: |
30ms |
get tp. blocked users: |
1ms |
| others: | 247ms |
| total: | 350ms |

| 0 / 0 |
