нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA.
Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
09.07.06 05:15: Перенесено модератором из 'C/C++' — Павел Кузнецов
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Простите за глупый вопрос, ситуация такая:
Р>нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA. Р>Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
Нужно, чтобы при определении и при использовании сигнатуры совпадали.
// В Dllextern"C"__declspec(dllexport) void __stdcall Func()
{
}
// В Exeextern"C"__declspec(dllimport) void __stdcall Func();
Здравствуйте, _nn_, Вы писали:
__>Здравствуйте, Ракопаукодав, Вы писали:
Р>>Простите за глупый вопрос, ситуация такая:
Р>>нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA. Р>>Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
__>Нужно, чтобы при определении и при использовании сигнатуры совпадали.
__>
__>// В Dll
__>extern"C"__declspec(dllexport) void __stdcall Func()
__>{
__>}
__>// В Exe
__>extern"C"__declspec(dllimport) void __stdcall Func();
__>
Невозможно. К тому же когда так определяешь, всё равно получается что-то типа ?Func@XA. А в dll (не моей) функция определена именно как sdtcall с экспортным именем Func
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Здравствуйте, _nn_, Вы писали:
__>>Здравствуйте, Ракопаукодав, Вы писали:
Р>>>Простите за глупый вопрос, ситуация такая:
Р>>>нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA. Р>>>Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
__>>Нужно, чтобы при определении и при использовании сигнатуры совпадали.
__>>
__>>// В Dll
__>>extern"C"__declspec(dllexport) void __stdcall Func()
__>>{
__>>}
__>>// В Exe
__>>extern"C"__declspec(dllimport) void __stdcall Func();
__>>
Р>Невозможно. К тому же когда так определяешь, всё равно получается что-то типа ?Func@XA. А в dll (не моей) функция определена именно как sdtcall с экспортным именем Func
Здравствуйте, Ракопаукодав, Вы писали:
Р>Невозможно. К тому же когда так определяешь, всё равно получается что-то типа ?Func@XA. А в dll (не моей) функция определена именно как sdtcall с экспортным именем Func
Дополнительно используйте def файл:
EXPORTS
Func=?Func@XA
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, gear nuke, Вы писали:
GN>Здравствуйте, Ракопаукодав, Вы писали:
Р>>Невозможно. К тому же когда так определяешь, всё равно получается что-то типа ?Func@XA. А в dll (не моей) функция определена именно как sdtcall с экспортным именем Func
GN>Дополнительно используйте def файл: GN>
GN>EXPORTS
GN>Func=?Func@XA
GN>
def-файл нужно использовать при компиляции dll, которую я не компилирую. а если бы и компилировал, то всё равно функция должна экспортироваться с именем Func
Или можно использовать такой def-файл и при импорте? Тогда что должно стоять в заголовке и куда его подключать?
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Простите за глупый вопрос, ситуация такая:
Р>нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA. Р>Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
У тебя скорее всего неправельный .lib файл, с которым ты линкуешь свой код. Посмотри, как там обзывается твоя функция с помощью dumpbin /exports yourlib.lib. Линкер, освовываясь на информации, которую он находит в lib файле, связывает твой код с динамически экспортируемыми функциями из dll. Поэтому если exe ищет ?Func@XXZZYYA, то это линкер связал его с ?Func@XXZZYYA.
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Ракопаукодав, Вы писали:
Р>>Простите за глупый вопрос, ситуация такая:
Р>>нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA. Р>>Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
A>У тебя скорее всего неправельный .lib файл, с которым ты линкуешь свой код. Посмотри, как там обзывается твоя функция с помощью dumpbin /exports yourlib.lib. Линкер, освовываясь на информации, которую он находит в lib файле, связывает твой код с динамически экспортируемыми функциями из dll. Поэтому если exe ищет ?Func@XXZZYYA, то это линкер связал его с ?Func@XXZZYYA.
Я ошибся: это линковщик ищет ?Func@XXZZYYA. Lib-файл правильный
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Здравствуйте, _nn_, Вы писали:
__>>
__>>// В Dll
__>>extern"C"__declspec(dllexport) void __stdcall Func()
__>>{
__>>}
__>>// В Exe
__>>extern"C"__declspec(dllimport) void __stdcall Func();
__>>
Р>Невозможно. К тому же когда так определяешь, всё равно получается что-то типа ?Func@XA. А в dll (не моей) функция определена именно как sdtcall с экспортным именем Func
Ты что-то напутал. extern "C" __declspec(dllimport) void __stdcall Func(); приводит к импорту функции с недекорированным именем. Все Win32 функции так импортируются.
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Ракопаукодав, Вы писали:
Р>>Здравствуйте, _nn_, Вы писали:
__>>>
__>>>// В Dll
__>>>extern"C"__declspec(dllexport) void __stdcall Func()
__>>>{
__>>>}
__>>>// В Exe
__>>>extern"C"__declspec(dllimport) void __stdcall Func();
__>>>
Р>>Невозможно. К тому же когда так определяешь, всё равно получается что-то типа ?Func@XA. А в dll (не моей) функция определена именно как sdtcall с экспортным именем Func
A>Ты что-то напутал. extern "C" __declspec(dllimport) void __stdcall Func(); приводит к импорту функции с недекорированным именем. Все Win32 функции так импортируются.
Нет, он импортирует функцию с декорированным именем: см. ошибку линковки
Error 1 error LNK2019: unresolved external symbol __imp__RunCalc@16 referenced in function _wmain ExportDll.obj
А вот если extern "C" __declspec(dllimport) void Func(); — тогда другое дело
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
приводит к импорту функции с недекорированным именем. Все Win32 функции так импортируются.
Р>Нет, он импортирует функцию с декорированным именем: см. ошибку линковки Р>Error 1 error LNK2019: unresolved external symbol __imp__RunCalc@16 referenced in function _wmain ExportDll.obj
Р>А вот если
Здравствуйте, Ракопаукодав, Вы писали:
Р>Нет, он импортирует функцию с декорированным именем: см. ошибку линковки Р>Error 1 error LNK2019: unresolved external symbol __imp__RunCalc@16 referenced in function _wmain ExportDll.obj
Значит у тебя количество параметров неправильное. @16 — это сколько байт на стеке являются параметрами к функции в __stdcall. В конвенции __stdcall функция сама очищает стек (ret 16 предполагается в твоём случае). Поэтому тот, кто её вызывает, должен заполнить стек правильным количеством параметров.
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Ракопаукодав, Вы писали:
Р>>Нет, он импортирует функцию с декорированным именем: см. ошибку линковки Р>>Error 1 error LNK2019: unresolved external symbol __imp__RunCalc@16 referenced in function _wmain ExportDll.obj
A>Значит у тебя количество параметров неправильное. @16 — это сколько байт на стеке являются параметрами к функции в __stdcall. В конвенции __stdcall функция сама очищает стек (ret 16 предполагается в твоём случае). Поэтому тот, кто её вызывает, должен заполнить стек правильным количеством параметров.
Это не у меня неправильно, а у тебя: модификатор
extern"C"
декларирует процедуру с соглашением о вызовах cdecl, а
__stdcall
— с соглашением stdcall, их просто нельзя вместе использовать
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, ekamaloff, Вы поставили мне минус, дак объясните.
Р>>>Нет, он импортирует функцию с декорированным именем: см. ошибку линковки Р>>>Error 1 error LNK2019: unresolved external symbol __imp__RunCalc@16 referenced in function _wmain ExportDll.obj
A>>Значит у тебя количество параметров неправильное. @16 — это сколько байт на стеке являются параметрами к функции в __stdcall. В конвенции __stdcall функция сама очищает стек (ret 16 предполагается в твоём случае). Поэтому тот, кто её вызывает, должен заполнить стек правильным количеством параметров.
Р>Это не у меня неправильно, а у тебя: модификатор
extern"C"
Р> декларирует процедуру с соглашением о вызовах cdecl, а
__stdcall
— с соглашением stdcall, их просто нельзя вместе использовать
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, MShura, Вы писали:
Р>>Это не у меня неправильно, а у тебя: модификатор
extern"C"
Р>> декларирует процедуру с соглашением о вызовах cdecl, а
__stdcall
— с соглашением stdcall, их просто нельзя вместе использовать
MS>extern "C" запрещает mangle имен
MS>Я так думаю, что минус вам поставлен за то, что поленились почитать документацию, прежде чем утверждать неверные вещи.
1. Во первых, я не поленился. Я ведь не говорю что я гуру, могу и неправильно что-нибдуь понять
2. Если вы такой умный, скажите, почему в dll при extern "C" и __stdcall имена функций становятся типа Func@16 и как этого избежать. Минусы все ставить могут, а вот помочь советом почему-то за 2 дня ещё никто не смог
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, ekamaloff, Вы писали:
E>Здравствуйте, Ракопаукодав, Вы писали:
Р>>скажите, почему в dll при extern "C" и __stdcall имена функций становятся типа Func@16
E>Name Decoration
E>Там даже табличка есть, что и как декорируется при разных сочетаниях calling convention и extern "C"
Р>> и как этого избежать.
E>Использовать .def файл и поиск по RSDN.
.def файл я могу использовать при экспорте. А как мне его при импорте использовать? Я уже искал и не только по RSDN
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Р>.def файл я могу использовать при экспорте. А как мне его при импорте использовать? Я уже искал и не только по RSDN
Я не очень знаю C++, но, по моему, если ты не можешь собрать dll с def-файлом, то тебе уже на C++ ничего не поможет , я всегда знал, что Delphi — это круто, но что б настолько
P.S. Не слушай тех, кто ставит минусы за невнимательность, а сам даже ветку прочитать полностью не может
Здравствуйте, ekamaloff, Вы писали что надо внимательнее читать документацию, а вот векту вы прочитали невнимательно:
E>Использовать .def файл и поиск по RSDN.
спрашивал КАК это сделать
FDS>По моему, то что он хочеть просто невозможно
Вместо того, чтобы пытаться понять, что нужно сделать, и в чём у него проблема, он хочет доказать неправоту тех, кто хочет ему помочь. Так он очень долго промается со своей плёвой, честно говоря, проблемой.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Простите за глупый вопрос, ситуация такая:
Р>нужно в VS2005 импортировать из dll функцию stdcall, однако при запуске программы он вместо функции Func ищет функцию, типа ?Func@XXZZYYA. Р>Использование директивы extern "C" не проходит, так как вызвать нужно именно stdcall
Попробуй для каждой ф-ции прописывать это:
#pragma comment(linker, "/export:MyFunc=?MyFunc@@YG_NH@Z")
это конечно не лучшее решение, но работает правда в експорте будут оба варианта ф-ции эффект тот же, что и от .def файла.
Р>2. почему в dll при extern "C" и __stdcall имена функций становятся типа Func@16 и как этого избежать. Минусы все ставить могут, а вот помочь советом почему-то за 2 дня ещё никто не смог
__stdcall добавляет @XXX, но это не является причиной вашей проблемы.
Если у Вас есть my.dll и вы хотите неявно загрузить её, то нужно использовать библиотеку импорта.
Это файл my.lib, который описывает экспортируемые функции. Он создается одновременно с my.dll и должен даваться разработчиками библиотеки.
Чтобы его использовать нужно дать линкеру соответсвующую комманду либо из проекта, либо в makefile, либо прямо в тексте исполняемой программы (#pragma comment(lib, "my.lib")
Даже если my.dll экспортирует "чистое" имя Func, то в библиотеке my.lib будет "нормальное" имя Func@0 и линкер легко найдет нужную функцию.
Если my.lib нет или библиотека была создана не MS совместимым компилятором, то это совершенно другой разговор.
Здравствуйте, MShura, Вы писали:
Р>>2. почему в dll при extern "C" и __stdcall имена функций становятся типа Func@16 и как этого избежать. Минусы все ставить могут, а вот помочь советом почему-то за 2 дня ещё никто не смог
MS>__stdcall добавляет @XXX, но это не является причиной вашей проблемы. MS>Если у Вас есть my.dll и вы хотите неявно загрузить её, то нужно использовать библиотеку импорта. MS>Это файл my.lib, который описывает экспортируемые функции. Он создается одновременно с my.dll и должен даваться разработчиками библиотеки. MS>Чтобы его использовать нужно дать линкеру соответсвующую комманду либо из проекта, либо в makefile, либо прямо в тексте исполняемой программы (#pragma comment(lib, "my.lib")
MS>Даже если my.dll экспортирует "чистое" имя Func, то в библиотеке my.lib будет "нормальное" имя Func@0 и линкер легко найдет нужную функцию. MS>Если my.lib нет или библиотека была создана не MS совместимым компилятором, то это совершенно другой разговор.
Кстати любопытный вопрос: можно ли статически связать свою прогу с чужой DLL (к примеру, подцепить NtQueryInformationFile из ntdll.dll) не имея к ней lib и не создавая для этого фейковый lib.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
CC>Кстати любопытный вопрос: можно ли статически связать свою прогу с чужой DLL (к примеру, подцепить NtQueryInformationFile из ntdll.dll) не имея к ней lib и не создавая для этого фейковый lib.
Боюсь, что стандартными линкерами тут не обойдешься.
Ведь линкер должен будет создать запись в таблице импорта и заглушки (корректируеются при загрузке библиотеки по конкретному адресу), для этого нормальному линкеру и нужна библиотека импорта (от пользователя) и список используемых функций (от компилятора).
CC>>Кстати любопытный вопрос: можно ли статически связать свою прогу с чужой DLL (к примеру, подцепить NtQueryInformationFile из ntdll.dll) не имея к ней lib и не создавая для этого фейковый lib.
MS>Боюсь, что стандартными линкерами тут не обойдешься. MS>Ведь линкер должен будет создать запись в таблице импорта и заглушки (корректируеются при загрузке библиотеки по конкретному адресу), для этого нормальному линкеру и нужна библиотека импорта (от пользователя) и список используемых функций (от компилятора).
Жаль что нет средств для того, чтобы прагмами или опциями линкера сымитировать линковку с libой от нужной DLLки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, CreatorCray, Вы писали:
CC>Здравствуйте, MShura, Вы писали:
CC>>>Кстати любопытный вопрос: можно ли статически связать свою прогу с чужой DLL (к примеру, подцепить NtQueryInformationFile из ntdll.dll) не имея к ней lib и не создавая для этого фейковый lib.
MS>>Боюсь, что стандартными линкерами тут не обойдешься. MS>>Ведь линкер должен будет создать запись в таблице импорта и заглушки (корректируеются при загрузке библиотеки по конкретному адресу), для этого нормальному линкеру и нужна библиотека импорта (от пользователя) и список используемых функций (от компилятора).
CC>Жаль что нет средств для того, чтобы прагмами или опциями линкера сымитировать линковку с libой от нужной DLLки.
Спасибо за отзывы, но руки у меня оказались слишком кривые:
Я второпях забыл подключить lib-файл к проекту , так что задачка даже ещё хуже оказалась
Есть только lib файл Delphi (не знаю какой именно версии, или 5-ой или 7-ой, скорее всего) и сама dll.
Когда его подключил выдалась ошибка
"fatal error LNK1107: invalid or corrupt file: cannot read at 0x310 e:\Prg\temp\110706\Import\exdpr.lib",
если подключаю в проект lib-файл, с определением
Здравствуйте, MShura, Вы писали:
FDS>>Да, а вот в Delphi — легко!
MS>Можно подробней? MS>DLL загружается загрузчиком PE или все-же самим приложением?
MS>В VC можно воспользоваться таким вариантом "отложенной" загрузки MS>http://www.rsdn.ru/article/cpp/delayload.xml
Я не знаю как она загружается , если нужно, могу посмотреть в дизассемблере
Важно то, что для программиста это выглядит как статический импорт со всеми удобствами, а динамический импорт реализуется явно как вызовы API — что не так удобно.
MS>>Можно подробней? MS>>DLL загружается загрузчиком PE или все-же самим приложением?
MS>>В VC можно воспользоваться таким вариантом "отложенной" загрузки MS>>http://www.rsdn.ru/article/cpp/delayload.xml
FDS>Я не знаю как она загружается , если нужно, могу посмотреть в дизассемблере
Достаточно посмотреть dependecies исполняемого файла или dumpbin /imports your.exe.
Будет ли среди импортных dll ваша dll.
Если будет, то эту dll загрузит загрузчик файла
FDS>Важно то, что для программиста это выглядит как статический импорт со всеми удобствами, а динамический импорт реализуется явно как вызовы API — что не так удобно.
Как программа будет себя вести, если:
— не найдет нужной dll
— не найдет нужной функции в dll
Насколько я понял автора топика он пытался использовать dll скомпиленную не по правилам MS, как если бы она была таковой.
Естественно получил проблему.
То что Дельфи знает формат MS ( иначе она не смогла бы компилиться с kernel32.lib ) это конечно хорошо, но должна ли MS знать формат Дельфи?
Здравствуйте, MShura, Вы писали:
MS>>>Можно подробней? MS>>>DLL загружается загрузчиком PE или все-же самим приложением?
MS>>>В VC можно воспользоваться таким вариантом "отложенной" загрузки MS>>>http://www.rsdn.ru/article/cpp/delayload.xml
FDS>>Я не знаю как она загружается , если нужно, могу посмотреть в дизассемблере
MS>Достаточно посмотреть dependecies исполняемого файла или dumpbin /imports your.exe. MS>Будет ли среди импортных dll ваша dll. MS>Если будет, то эту dll загрузит загрузчик файла
Например, import.exe использует функцию EX из exdpr.dll:
dumpbin /imports import.exe.
...
exdpr.dll
40B214 Import Address Table
0 Import Name Table
0 time date stamp
0 Index of first forwarder reference
0 EX
...
Смотрел своим просмотрщиком — то же говорит, что есть в секции импорта
MS>Как программа будет себя вести, если: MS>- не найдет нужной dll
Диалог при запуске (до исполнения какого-либо кода, даже если он не относится к импортируемым функиям)
---------------------------
Import.exe — Не удалось найти компонент
---------------------------
Приложению не удалось запуститься, поскольку exdpr.dll не был найден. Повторная установка приложения может исправить эту проблему.
---------------------------
ОК
---------------------------
MS>- не найдет нужной функции в dll
Диалог при запуске
---------------------------
Import.exe — Точка входа не найдена
---------------------------
Точка входа в процедуру _EX@4 не найдена в библиотеке DLL exdpr.dll.
---------------------------
ОК
---------------------------
MS>Насколько я понял автора топика он пытался использовать dll скомпиленную не по правилам MS, как если бы она была таковой. MS>Естественно получил проблему. MS>То что Дельфи знает формат MS ( иначе она не смогла бы компилиться с kernel32.lib ) это конечно хорошо, но должна ли MS знать формат Дельфи?
Не. Не так. Delphi не знает формат MS! Delphi знает как только генерировать PE-файл.
В секции импорта PE-файла пишется название dll и имя импортируемой функции и всё. Остальное делает загрузчик Windows.
То есть Delphi никаких lib-файлов не требуется. Я могу импортировать функцию из любой dll, если знаю её имя или индекс, название dll и соглашение о вызове (и сигнатуру). То есть, если я хочу импортировать функцию EX из exdpr.dll, но при этом она скомпилирована MS VC с модификаторами extern "C" и __stdcall то мне нужно написать строку
function EX(var Data: integer): integer; stdcall; external'exdpr.dll' name '_EX@4';
и больше ничего не надо, кроме файла exdpr.dll во время исполнения в надлежащей директории.
MS должна позволять импортировать функции независимо от того, кто скомпилировал dll — Delphi это позволяет. Странно что MS — нет. Я был очень удивлён, но сам ничего в справке не нашёл по этому поводу.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Спасибо за отзывы, но руки у меня оказались слишком кривые:
Р>Я второпях забыл подключить lib-файл к проекту , так что задачка даже ещё хуже оказалась
Р>Есть только lib файл Delphi (не знаю какой именно версии, или 5-ой или 7-ой, скорее всего) и сама dll.
Р>Когда его подключил выдалась ошибка Р>"fatal error LNK1107: invalid or corrupt file: cannot read at 0x310 e:\Prg\temp\110706\Import\exdpr.lib", Р>если подключаю в проект lib-файл, с определением Р>
Р>скомпилированный на C++ — то всё нормально, но у меня такого файла на самом деле нет.
Р>В общем, чую придётся использовать динамический импорт , как подсказывали выше
Р>Я НЕ могу перекомпилировать dll — она из другой фирмы и у меня нет исходных кодов.
По идее, если всё-таки попросить ребят перекомпилировать dll с декорированными именами, lib-файл можно создать путём компиляции "пустой" dll с такими же функциями.
То есть компилишь dll-ку с функцией EX, в которой есть одна строка — return 0; на C++
Перекомпилируешь реальную dll с функцией EX на функцию _EX@4
Компилишь своё приложение с подложным lib-файлом и подкладываешь реальную dll с изменёнными вариантами
<Доказательства загрузки dll загрузчиком PE пропущены>
MS>>Насколько я понял автора топика он пытался использовать dll скомпиленную не по правилам MS, как если бы она была таковой. MS>>Естественно получил проблему. MS>>То что Дельфи знает формат MS ( иначе она не смогла бы компилиться с kernel32.lib ) это конечно хорошо, но должна ли MS знать формат Дельфи?
FDS>Не. Не так. Delphi не знает формат MS! Delphi знает как только генерировать PE-файл. FDS>В секции импорта PE-файла пишется название dll и имя импортируемой функции и всё. Остальное делает загрузчик Windows. FDS>То есть Delphi никаких lib-файлов не требуется. Я могу импортировать функцию из любой dll, если знаю её имя или индекс, название dll и соглашение о вызове (и сигнатуру). То есть, если я хочу импортировать функцию EX из exdpr.dll, но при этом она скомпилирована MS VC с модификаторами extern "C" и __stdcall то мне нужно написать строку FDS>
FDS>function EX(var Data: integer): integer; stdcall; external'exdpr.dll' name '_EX@4';
FDS>
FDS>и больше ничего не надо, кроме файла exdpr.dll во время исполнения в надлежащей директории.
Неужели все функции из SDK\include нужно явно описывать таким образом?
FDS>MS должна позволять импортировать функции независимо от того, кто скомпилировал dll — Delphi это позволяет. Странно что MS — нет. Я был очень удивлён, но сам ничего в справке не нашёл по этому поводу.
Это напоминает разницу между C и C++.
Явно загружая библиотеку мы делаем явный каст с надеждой что ничего в экспортируемой функции не поменялось (см выделенное).
Неужели не было ошибок с предполагаемым и реальным типом функций?
Использование библиотеки импорта повышает надежность обеспечивая дополнительную провеку на этапе линковки.
P.S.
Согласен, что было бы неплохо иметь возможность перенести ответственность с линкера на пользователя так, как это реализовано в Дельфи.
Хотя как например импортировать функции подверженные C++ искажению имен или более того импортировать классы?
В этом случае лучше библиотеки импорта трудно придумать.
Здравствуйте, MShura, Вы писали:
FDS>>То есть Delphi никаких lib-файлов не требуется. Я могу импортировать функцию из любой dll, если знаю её имя или индекс, название dll и соглашение о вызове (и сигнатуру). То есть, если я хочу импортировать функцию EX из exdpr.dll, но при этом она скомпилирована MS VC с модификаторами extern "C" и __stdcall то мне нужно написать строку FDS>>
FDS>>function EX(var Data: integer): integer; stdcall; external'exdpr.dll' name '_EX@4';
FDS>>
FDS>>и больше ничего не надо, кроме файла exdpr.dll во время исполнения в надлежащей директории.
MS>Неужели все функции из SDK\include нужно явно описывать таким образом?
Да, они так и описаны в подключаемых файлах библиотек.
FDS>>MS должна позволять импортировать функции независимо от того, кто скомпилировал dll — Delphi это позволяет. Странно что MS — нет. Я был очень удивлён, но сам ничего в справке не нашёл по этому поводу.
MS>Это напоминает разницу между C и C++.
MS>Явно загружая библиотеку мы делаем явный каст с надеждой что ничего в экспортируемой функции не поменялось (см выделенное). MS>Неужели не было ошибок с предполагаемым и реальным типом функций? MS>Использование библиотеки импорта повышает надежность обеспечивая дополнительную провеку на этапе линковки.
Конечно, случаются. Но ведь и lib можно взять не той версии. Это было бы хорошо, если бы lib-ы были у всех одинаковыми
MS>P.S. MS>Согласен, что было бы неплохо иметь возможность перенести ответственность с линкера на пользователя так, как это реализовано в Дельфи. MS>Хотя как например импортировать функции подверженные C++ искажению имен или более того импортировать классы? MS>В этом случае лучше библиотеки импорта трудно придумать.
М-да. Хотя я классы никогда не импортировал , тогда уж сразу COM надо использовать.
Здравствуйте, FDSC, Вы писали:
FDS>Здравствуйте, FDSC, Вы писали:
FDS>Если это не годится, можно после компиляции в exe искать строки типа _EX@4 и прямо в файле заменять их на EX\x0\x0\x0
Ну, это извращения. Лучше уж динамический импорт
Спасибо всем
Поль вдруг вскочил и с необыкновенной живостью изобразил ракопаука. Отвратительный скрежещущий вой многоногого чудовища, пробирающегося через джунгли страшной Пандоры, огласил окрестности. И, словно в ответ, издалека донёсся глубокий ревущий вздох.
Здравствуйте, Ракопаукодав, Вы писали:
Р>Спасибо за отзывы, но руки у меня оказались слишком кривые:
Р>Я второпях забыл подключить lib-файл к проекту , так что задачка даже ещё хуже оказалась
Р>Есть только lib файл Delphi (не знаю какой именно версии, или 5-ой или 7-ой, скорее всего) и сама dll.
Борландовские и майкрософтовские lib — файлы несовместимы.
Здравствуйте, MShura, Вы писали:
FDS>>Да, а вот в Delphi — легко!
MS>Можно подробней? MS>DLL загружается загрузчиком PE или все-же самим приложением?
MS>В VC можно воспользоваться таким вариантом "отложенной" загрузки MS>http://www.rsdn.ru/article/cpp/delayload.xml
Здравствуйте, MShura, Вы писали:
MS>Неужели все функции из SDK\include нужно явно описывать таким образом?
Ничего подобного. Если речь идет о функциях WinAPI, то они экспортируются из dll по недекорированному имени и следовательно импортируются в delphi по нему же. Вот вырезка из Windows.pas:
function CreateDialogParamA; external user32 name 'CreateDialogParamA';
function CreateDialogParamW; external user32 name 'CreateDialogParamW';
function CreateDialogParam; external user32 name 'CreateDialogParamA';
function CreateIcon; external user32 name 'CreateIcon';
function CreateIconFromResource; external user32 name 'CreateIconFromResource';
function CreateIconFromResourceEx; external user32 name 'CreateIconFromResourceEx';
function CreateIconIndirect; external user32 name 'CreateIconIndirect';
function CreateMDIWindowA; external user32 name 'CreateMDIWindowA';
function CreateMDIWindowW; external user32 name 'CreateMDIWindowW';
function CreateMDIWindow; external user32 name 'CreateMDIWindowA';
function CreateMenu; external user32 name 'CreateMenu';
function CreatePopupMenu; external user32 name 'CreatePopupMenu';
function CreateWindowExA; external user32 name 'CreateWindowExA';
function CreateWindowExW; external user32 name 'CreateWindowExW';
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
MS>>Неужели все функции из SDK\include нужно явно описывать таким образом?
E>Ничего подобного. Если речь идет о функциях WinAPI, то они экспортируются из dll по недекорированному имени и следовательно импортируются в delphi по нему же. Вот вырезка из Windows.pas:
E>
E>function CreateDialogParamA; external user32 name 'CreateDialogParamA';
....
E>
Насколько я понял файл windows.h из Platform SDK не подключается?
Означает ли Windows.pas дублирует файл windows.h и все остальное?
Практикуется ли использование макросов (например CreateDialogParam) в Дельфи?
Кто этот макрос определяет (если не включается файл windows.h)
Я не знаю с какой частотой обновляется Дельфи, но Platform SDK регулярно обновляется.
К счастью старые функции не меняются, а новые функции добавляются постоянно.
Значит ли это что нужно самому править файл Windows.pas?
MS>>>Неужели все функции из SDK\include нужно явно описывать таким образом?
E>>Ничего подобного. Если речь идет о функциях WinAPI, то они экспортируются из dll по недекорированному имени и следовательно импортируются в delphi по нему же. Вот вырезка из Windows.pas:
E>>
E>>function CreateDialogParamA; external user32 name 'CreateDialogParamA';
MS>....
E>>
MS>Насколько я понял файл windows.h из Platform SDK не подключается? MS>Означает ли Windows.pas дублирует файл windows.h и все остальное?
windows.pas и есть windows.h
MS>Практикуется ли использование макросов (например CreateDialogParam) в Дельфи? MS>Кто этот макрос определяет (если не включается файл windows.h)
?
MS>Я не знаю с какой частотой обновляется Дельфи, но Platform SDK регулярно обновляется. MS>К счастью старые функции не меняются, а новые функции добавляются постоянно. MS>Значит ли это что нужно самому править файл Windows.pas?
Здравствуйте, ekamaloff, Вы писали:
E>Здравствуйте, MShura, Вы писали:
MS>>Неужели все функции из SDK\include нужно явно описывать таким образом?
E>Ничего подобного. Если речь идет о функциях WinAPI, то они экспортируются из dll по недекорированному имени и следовательно импортируются в delphi по нему же. Вот вырезка из Windows.pas:
Здравствуйте, FDSC, Вы писали:
MS>>Я не знаю с какой частотой обновляется Дельфи, но Platform SDK регулярно обновляется. MS>>К счастью старые функции не меняются, а новые функции добавляются постоянно. MS>>Значит ли это что нужно самому править файл Windows.pas?
FDS>Это так же невозможно, как править windows.h
В Delphi определены не все функции и константы SDK. То, чего нет в стандартных модулях можно объявить самостоятельно в своих файлах. Иногда даже приходится переопределять функции, уже определённые в стандартных модулях (очень редко)
Здравствуйте, MShura, Вы писали:
MS>Насколько я понял файл windows.h из Platform SDK не подключается? MS>Означает ли Windows.pas дублирует файл windows.h и все остальное?
Хидеры вообще в дельфи не подключаются. Windows.pas это и есть windows.h
MS>Практикуется ли использование макросов (например CreateDialogParam) в Дельфи? MS>Кто этот макрос определяет (если не включается файл windows.h)
Вместо макросов пишутся функции , например такие:
function CreateWindow(lpClassName: PChar; lpWindowName: PChar;
dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND;
hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND;
begin
Result := CreateWindowEx(0, lpClassName, lpWindowName, dwStyle, X, Y,
nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
end;
MS>Я не знаю с какой частотой обновляется Дельфи, но Platform SDK регулярно обновляется. MS>К счастью старые функции не меняются, а новые функции добавляются постоянно. MS>Значит ли это что нужно самому править файл Windows.pas?
Если какой-то функции нет, обычно делают свой модуль (типа WindowsEx.pas) и в него пихают все недостающие объявления. Стандартные модули изменять нельзя
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
It is always bad to give advices, but you will be never forgiven for a good one.
Oscar Wilde
MS>>Практикуется ли использование макросов (например CreateDialogParam) в Дельфи? MS>>Кто этот макрос определяет (если не включается файл windows.h)
E>Вместо макросов пишутся функции , например такие:
E>
В Platform SDK CreateWindow и CreateWindowEx — суть макросы, определенные в winuser.h (включается из windows.h)
Судя по всему в Дельфи это уже не макросы?
Именно это я и хотел узнать.
Если это не макросы, то можно ли писать программы с использованием TCHAR?
FDS>>>Да, а вот в Delphi — легко!
MS>>Можно подробней? MS>>DLL загружается загрузчиком PE или все-же самим приложением?
MS>>В VC можно воспользоваться таким вариантом "отложенной" загрузки MS>>http://www.rsdn.ru/article/cpp/delayload.xml
Здравствуйте, MShura, Вы писали:
MS>>>Практикуется ли использование макросов (например CreateDialogParam) в Дельфи? MS>>>Кто этот макрос определяет (если не включается файл windows.h)
E>>Вместо макросов пишутся функции , например такие:
E>>
MS>В Platform SDK CreateWindow и CreateWindowEx — суть макросы, определенные в winuser.h (включается из windows.h) MS>Судя по всему в Дельфи это уже не макросы? MS>Именно это я и хотел узнать.
MS>Если это не макросы, то можно ли писать программы с использованием TCHAR?
Естественно нельзя. Нужно писать программы с использованием WideChar (WideString), если вы любите Unicode и char в противном случае
топике, наверняка автору будет интересно поправить
Уже до меня писали. Автор ответил что поправить нет возможности по причине наличия отсутствия у него вышеуказанного компилятора.
Кроме того, с подрузкой через LoadLibrary я и сам могу. Тем более там всего то одна функция. Трабл в том, что надо это в LIB-проекте который отдается в виде "связка один .lib файл + n .h файлов" отдается на юзание во втором проекте. И хотелось бы как нить извратнуться чтоб в эту либу присоединить ссылку на эту функцию для того чтоб к получившемуся во втором проекте EXEшнику все нужное прилинковалось статически.
Может быть есть еще и вариант с постбилд обработкой lib-ы путем какого нить merge с фейковой либой для нужной DLL, но пока что то у меня на эту тему не получается ничего
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
топике, наверняка автору будет интересно поправить CC>Уже до меня писали. Автор ответил что поправить нет возможности по причине наличия отсутствия у него вышеуказанного компилятора.
Ну так и ICL7 нет. Однако adontz не поленился откомпилить и проанализировать проблемы. В результате все заработало.
Кстати, возможно, новые версии будут на 9-ке вполне работать — большинство несовместимости из-за макросов, а с некоторого времени там бустовские можно пользовать заместо нативных (DL_USE_BOOST_PP).
топике, наверняка автору будет интересно поправить CC>>Уже до меня писали. Автор ответил что поправить нет возможности по причине наличия отсутствия у него вышеуказанного компилятора.
AS>Ну так и ICL7 нет. Однако adontz не поленился откомпилить и проанализировать проблемы. В результате все заработало. AS>Кстати, возможно, новые версии будут на 9-ке вполне работать — большинство несовместимости из-за макросов, а с некоторого времени там бустовские можно пользовать заместо нативных (DL_USE_BOOST_PP).
Да уже и надобность отпала — только что все заработало как мне надо было. Решение: создание фейковой DLL с либой и вписывание имени либы в строку линкера. Почему раньше это же глючило — хез.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Здравствуйте, Andrew S, Вы писали:
AS>Ну так и ICL7 нет. Однако adontz не поленился откомпилить и проанализировать проблемы. В результате все заработало.
Сорри, но свободного времени нету пока...
AS>Кстати, возможно, новые версии будут на 9-ке вполне работать — большинство несовместимости из-за макросов
Качал и пробовал не далее как вчера днем.
AS>, а с некоторого времени там бустовские можно пользовать заместо нативных (DL_USE_BOOST_PP).
Это хорошо только в том случае, когда буст уже используется в проекте. Если же нет — то подрубать этого монстра для компиляции одного файла что то не хочется.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
AS>>Кстати, возможно, новые версии будут на 9-ке вполне работать — большинство несовместимости из-за макросов CC>Качал и пробовал не далее как вчера днем.
С указаным дефином?
AS>>, а с некоторого времени там бустовские можно пользовать заместо нативных (DL_USE_BOOST_PP). CC>Это хорошо только в том случае, когда буст уже используется в проекте. Если же нет — то подрубать этого монстра для компиляции одного файла что то не хочется.
BOOST_PP уже стал монстром? Однако Вот только сделать его сильно меньше и при этом не потерять в совместимости — не получается. Кастрированный вариант в DL есть, но вот совместим он, похоже, только с препроцессором от m$. В IC9 EDG, посему только буст. Либо разбираться, что ему надо от варианта в библиотеке и пробовать найти общее между m$ и EDG. У бусте этого сделать не смогли, там раздельные макросы.
Здравствуйте, Andrew S, Вы писали:
AS>>>Кстати, возможно, новые версии будут на 9-ке вполне работать — большинство несовместимости из-за макросов CC>>Качал и пробовал не далее как вчера днем.
AS>С указаным дефином?
в смысле DL_USE_BOOST_PP?
Без него — буст для этого разворачивать крайне неохота.
AS>>>, а с некоторого времени там бустовские можно пользовать заместо нативных (DL_USE_BOOST_PP). CC>>Это хорошо только в том случае, когда буст уже используется в проекте. Если же нет — то подрубать этого монстра для компиляции одного файла что то не хочется.
AS>BOOST_PP уже стал монстром? Однако
Сам буст целиком давно уже монстер... А выковыривать из него части — жаль времени.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока