On 01.12.2010 14:12, alexander51 wrote:
> в этом нет смысла, т.к. это и так уже стало понятно. Но на чтение книжек уйдут > месяцы, а эта библиотека нужна мне в рабочем состоянии чем быстрее, тем лучше. > Поэтому я и не прошу Вас излагать тут всю теорию сборки C, а лишь «слегка», в > двух словах, как это сделали первые ответившие, подсказать, что не так.
Лучший совет: обратитесь к профессионалам, раз так надо, но не умеете.
Так просто это за 5 мин. не объясниш.
---
Имеется dll и заголовочный файл к ней.
---
Этого для подключения библиотеки МАЛО. нужно иметь библиотеку ипморта ещё.
On 29.11.2010 12:14, Аноним 38 wrote: > Подключая динамически, делал так (меняя CALLCONV обратно на __stdcall): > > #typedef void (__stdcall PFN_FncName*)(parameters) > … > HINSTANCE handle = ::LoadLibrary((LPCSTR)("mydll.dll")); > PFN_FncName pfn_FncName = (PFN_FncName) ::GetProcAddress(handle, "FncName"); > … > pfn_FncName(Parameters);
Это -- неверный способ вызова функции из .DLL. Он может работать, а может
и НЕ работать.
Posted via RSDN NNTP Server 2.1 beta
Не получается подключить dll
От:
Аноним
Дата:
29.11.10 09:14
Оценка:
Здравствуйте, уважаемые господа. На днях столкнулся с проблемой, суть следующая:
Имеется dll и заголовочный файл к ней. В заголовочном файле все функции объявлены так:
#define CALLCONV __stdcall
….
extern “C” RETURN_TYPE CALLCONV Fnc_Name(Parameters);
Подключая библиотеку статически, я менял CALLCONV на __declspec(dllimport) и на этапе выполнения проги в момент обращения к функциям получал ошибку:
Run-Time Check Failure #0 — The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.
Подключая динамически, делал так (меняя CALLCONV обратно на __stdcall):
В результате получал ту же самую ошибку. Как при статическом, так и при динамическом подключении вылетали не все функции. Некоторые выполнялись успешно.
Подскажите пож., в чем может быть дело? Заранее спасибо!
02.12.10 18:27: Перенесено модератором из 'C/C++' — Odi$$ey
Здравствуйте, uzhas, Вы писали:
U>Здравствуйте, Аноним, Вы писали:
А>>Подключая библиотеку статически, я менял CALLCONV на __declspec(dllimport) U>надо не менять, а дополнять. конвенция вызовов ортогональна импорту\экспорту U>http://www.experts-exchange.com/Programming/Languages/CPP/Q_10118794.html
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, уважаемые господа. На днях столкнулся с проблемой, суть следующая:
А>Имеется dll и заголовочный файл к ней. В заголовочном файле все функции объявлены так: А>#define CALLCONV __stdcall А>…. А>extern “C” RETURN_TYPE CALLCONV Fnc_Name(Parameters);
А>Подключая библиотеку статически, я менял CALLCONV на __declspec(dllimport)
Ты делал это неправильно.
А>Подключая динамически, делал так (меняя CALLCONV обратно на __stdcall):
Ты делал это тоже неправильно.
А>В результате получал ту же самую ошибку. Как при статическом, так и при динамическом подключении вылетали не все функции. Некоторые выполнялись успешно.
Просто повезло.
А не так вот что: сначала нужно знать, что делаешь, потом делать.
Всю теорию сборки в С тебе тут излагать нет смысла -- её можно найти в книгах или инете.
Здравствуйте, MasterZiv, Вы писали:
MZ>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, уважаемые господа. На днях столкнулся с проблемой, суть следующая:
А>>Имеется dll и заголовочный файл к ней. В заголовочном файле все функции объявлены так: А>>#define CALLCONV __stdcall А>>…. А>>extern “C” RETURN_TYPE CALLCONV Fnc_Name(Parameters);
А>>Подключая библиотеку статически, я менял CALLCONV на __declspec(dllimport)
MZ>Ты делал это неправильно.
А>>Подключая динамически, делал так (меняя CALLCONV обратно на __stdcall):
MZ>Ты делал это тоже неправильно.
А>>В результате получал ту же самую ошибку. Как при статическом, так и при динамическом подключении вылетали не все функции. Некоторые выполнялись успешно.
MZ>Просто повезло.
MZ>А не так вот что: сначала нужно знать, что делаешь, потом делать. MZ>Всю теорию сборки в С тебе тут излагать нет смысла -- её можно найти в книгах или инете.
Я понимаю, что без книжек далеко не уедешь. Прошу прощения за то, что не упомянул в первом посте про то, что я имею очень скудные познания в C, а теперь в этом нет смысла, т.к. это и так уже стало понятно. Но на чтение книжек уйдут месяцы, а эта библиотека нужна мне в рабочем состоянии чем быстрее, тем лучше. Поэтому я и не прошу Вас излагать тут всю теорию сборки C, а лишь «слегка», в двух словах, как это сделали первые ответившие, подсказать, что не так.
Также прошу прощения за синтаксические ошибки в своем первом посте, т.к. я писал его по памяти, не имея под рукой кода.
Сергей, uhaz, сбасибо большое, я понял ошибку — __stdcall в хэдере должен быть. Но непонятно, почему не работает случай динамического подключения. Ведь там хэдер от библиотеки вообще не используется, а __stdcall стоит в объявлении типа указателя на функцию. Подскажите пожалуйста… Провел довольно много времени за соответствующими статьями в инете, не нашел причину…
Код во вложении. http://files.rsdn.ru/94922/DynamicCNC.cpp
Здравствуйте, alexander51, Вы писали:
A> __stdcall в хэдере должен быть. Но непонятно, почему не работает случай динамического подключения. Ведь там хэдер от библиотеки вообще не используется, а __stdcall стоит в объявлении типа указателя на функцию. Подскажите пожалуйста… Провел довольно много времени за соответствующими статьями в инете, не нашел причину… A>Код во вложении. A>http://files.rsdn.ru/94922/DynamicCNC.cpp
ошибка про несответсвия ESP возникает (при включённой опции компилятора) в след случаях:
1. различная callingconversion (в MSWin32 основные: thiscall, ccall, stdcall, fastcall)
2. несовпадение числа и/или типов параметров
при этом типы должны быть разными по размеру в стеке. например double против int будет ошибка, а int против char нет.
ps
1. код безполезен, т.к. нет объявлений
2. не адо так много цитировать
3. надо форматировать текст использую кнопочки
Здравствуйте, alexander51, Вы писали:
A>Ведь там хэдер от библиотеки вообще не используется, а __stdcall стоит в объявлении типа указателя на функцию. Подскажите пожалуйста…
хедер как раз желательно использовать, ибо там правильное объявление экспортируемой функции
к сожалению, вы выложили мало кода (при длл и ее интерфейс забыли)
могу дать советы только в режиме телепатии:
1) используйте extern "C" когда объявляете функцию из чужой длл, скорей всего она имеет С-стайл декорирование
2) всегда проверяйте, что вернула GetProcAddress на ноль. сразу возвращайте ошибку, чтобы программа не падала
то же самое относится к LoadLibrary
3) возможно, в длл функция имеет другую сигнатуру и вы передаете неправильное число\тип аргументов
Здравствуйте, uzhas, Вы писали:
U>хедер как раз желательно использовать, ибо там правильное объявление экспортируемой функции
Желательно, но для динамического может и не помочь.
И в добавок, тут может быть одна тонкость. Если в хедере нет явного объявления calling convencion, то это может быть перекрыто опциями компилятора (проекта). Поэтому рекомедоуванно всегда ставить явно для библиотек (в т.ч. и импортных)
U>1) используйте extern "C" когда объявляете функцию из чужой длл, скорей всего она имеет С-стайл декорирование
необязательно
U>2) всегда проверяйте, что вернула GetProcAddress на ноль. сразу возвращайте ошибку, чтобы программа не падала
обязательно!
но вроде заявленная ошибка другая.
U>3) возможно, в длл функция имеет другую сигнатуру и вы передаете неправильное число\тип аргументов
ага
On 01.12.2010 18:49, uzhas wrote:
> 1) используйте extern "C" когда объявляете функцию из чужой длл, скорей всего > она имеет С-стайл декорирование
Неверно. Стайл может быть любой.
> 2) всегда проверяйте, что вернула GetProcAddress на ноль. сразу возвращайте > ошибку, чтобы программа не падала > то же самое относится к LoadLibrary
+1
А ещё -- не применяйте вообще динамическую загрузку DLL. Через линкер только.
> 3) возможно, в длл функция имеет другую сигнатуру и вы передаете неправильное > число\тип аргументов
Здравствуйте, MasterZiv, Вы писали:
MZ>On 01.12.2010 18:49, uzhas wrote:
>> 1) используйте extern "C" когда объявляете функцию из чужой длл, скорей всего >> она имеет С-стайл декорирование
MZ>Неверно. Стайл может быть любой.
я не утверждаю, что должен быть только Си-стайл при работе с длл
я посоветовал ТС его сменить, ибо
Имеется dll и заголовочный файл к ней. В заголовочном файле все функции объявлены так:
#define CALLCONV __stdcall
…. extern “C” RETURN_TYPE CALLCONV Fnc_Name(Parameters);
Подключая динамически, делал так (меняя CALLCONV обратно на __stdcall):
Не CmdMoveAxesDelta, а HidInitialize называется эта функция в библиотеке. Понятно — CmdMoveAxesDelta принимает аргументы, а HidInitialize — нет, поэтому похоже и все рушилось. Теперь от Run-Time Check Failure #0, кажется, избавился. Это при динамическом подключении. Хэдер я не подключал, взял оттуда только enum CNC_ERROR.
Что касается связывания через линкер.
Этого для подключения библиотеки МАЛО. нужно иметь библиотеку ипморта ещё.
Библиотека импорта — это lib? Я сделал файл def, используя dumpbin, из него — lib с помощью lib.exe. Подключил хэдер. Подключил lib при помощи #pragma comment (вместо прагмы ставил и в свойствах проекта). Ошибка unresolved external.
Спасибо большое Вам за советы, я посмотрю всё внимательно и, думаю, уже справлюсь Хэдер тут: http://files.rsdn.ru/94922/CNCUSBControllerAPI.h
On 02.12.2010 23:12, alexander51 wrote:
> Не CmdMoveAxesDelta, а HidInitialize называется эта функция в библиотеке. > Понятно — CmdMoveAxesDelta принимает аргументы, а HidInitialize — нет, поэтому > похоже и все рушилось. Теперь от Run-Time Check Failure #0, кажется, избавился. > Это при динамическом подключении. Хэдер я не подключал, взял оттуда только enum > CNC_ERROR.
Думаю, это только кажется.
> Библиотека импорта — это lib?
Да.
Я сделал файл def, используя dumpbin, из него — > lib с помощью lib.exe. Подключил хэдер. Подключил lib при помощи #pragma comment > (вместо прагмы ставил и в свойствах проекта). Ошибка unresolved external.
0) процесс .exe -> dumpbin -> .def -> .lib не всегда однозначно восстанавливает
всю информацию.
1) Пожет таки где-то ошибся.
Почему бы просто не взять из дистрибутива .lib и с ним собрать ?