Народ, у меня следующая проблема. Помогите, кто сможет, оч. надо!
В коде для Win32 API я явно подключаю некоторую DLL, чтобы потом вызывать её функции по адресу (разрешение имени в адрес). В итоге у меня есть указатель на требуемую функцию lpDllFunc. Я вызываю её из метода своего класса, например:
SomeClass::SomeMethod(Arg1 arg1, &Arg2 arg2)
{
long RetVal = (lpDllFunc)(arg1, arg2);
// Затем я присваиваю значения закрытым полям класса _attr1 и
// _attr2
this->_attr1 = 0;
this->_attr2 = 0;
}
Проблема в том, что к моменту возврата из библиотечной функции lpDllFunc, содержимое памяти, где записан указатель на объект, для которого вызван этот метод, т.е this, меняется, и я теряю указатель на объект, и программа падает на строке this->_attr1 = 0.
Т.е, например, если до вызова lpDllFunc:
&this = 0x00aa00bb и this = 0x00db98bc,
то после:
&this = 0x00aa00bb а this=0x00ffcc00.
ДО
0x00aa00bb : 0x00db98bc 00000000 (сюда пишется RetVal)
ПОСЛЕ
0x00aa00bb : 0x00ffcc00 bff012ce (получил RetVal)
Меняется содержимое памяти по адресу &this. Причем эта функция меняет 4 байта по адресу &this и записывает возвращаемое значение в следующие 4 байта памяти.
А если я компоную эту библиотеку неявно, то прямой вызов функции по имени все делает корректно и она записывает возвращаемое значение в те же следущие 4 байта после 4-х байтов с указателем this, а память &this не портит.
ДО
0x00aa00bb : 0x00db98bc 00000000 (сюда пишется RetVal)
ПОСЛЕ
0x00aa00bb : 0x00db98bc bff012ce (получил RetVal)
Явно комонуемая DLL. Гуру, помогите!!
Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
95% - использовано неправильное тип (соглашение) вызова. Все функции, загружаемые из DLL динамически, должны быть stdcall.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Этот трюк мне действительно необходим. А что значит функция должна быть stdcall? как это сделать?
- Romeo
- Сообщения: 3126
- Зарегистрирован: 02 мар 2004, 17:25
- Откуда: Крым, Севастополь
- Контактная информация:
Это не "трюк". Это квалификатор, который используется для измениния соглашения о передачи параметров. Выглядит это примерно так:
Код: Выделить всё
void __stdcall SomeFunction(...);
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Romeo, псасибо большое, проблема была именно в этом. Теперь усё работает!! 

Не обязательно, соглашение м.б. любое, главное, оно должно быть одинаковым в определении функции в DLL и в типе указателя на функцию при ее явном экспорте в целевом коде. Чаще всего используется __stdcall , это правда.95% - использовано неправильное тип (соглашение) вызова. Все функции, загружаемые из DLL динамически, должны быть stdcall.