Страница 1 из 1

Явно комонуемая DLL. Гуру, помогите!!

Добавлено: 13 дек 2005, 18:59
Redcat
Народ, у меня следующая проблема. Помогите, кто сможет, оч. надо!

В коде для 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)

Добавлено: 13 дек 2005, 19:27
Romeo
95% - использовано неправильное тип (соглашение) вызова. Все функции, загружаемые из DLL динамически, должны быть stdcall.

Добавлено: 13 дек 2005, 20:39
Redcat
Этот трюк мне действительно необходим. А что значит функция должна быть stdcall? как это сделать?

Добавлено: 13 дек 2005, 20:51
Romeo
Это не "трюк". Это квалификатор, который используется для измениния соглашения о передачи параметров. Выглядит это примерно так:

Код: Выделить всё

void __stdcall SomeFunction(...);

Добавлено: 14 дек 2005, 18:16
Redcat
Romeo, псасибо большое, проблема была именно в этом. Теперь усё работает!! :D

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