2013-03-22 3 views
1

Я пытаюсь написать приложение в VC++ версии 8. У меня есть DLL, с помощью хоста зависимостей. Я получил список API-интерфейсов, доступных в DLL.Как вызвать DLL-API

Я могу загрузить DLL.But когда я попытался вызвать некоторые из интерфейсов API в DLL, я тогда получаю эту ошибку отладки

«Run-Time Check Failure # 0 - значение ESP не было как правило, является результатом вызова функции, объявленной с одним вызовом, с указателем функции, объявленным с другим соглашением о вызовах ».

typedef void (WINAPI *RECEIVE_CALLBACK)int*, int); 

typedef void (WINAPI *MYPROC)(RECEIVE_CALLBACK); 

    ..... 
    ..... 

handleDll = LoadLibraryW((LPCWSTR)L"Example.dll"); 

ProcAdd = (MYPROC) GetProcAddress(handleDll, "[email protected]"); 

(ProcAdd) ((RECEIVE_CALLBACK) ReceiveFunc); 

Когда выполняется последняя строка, я получаю вышеуказанную ошибку. Что может быть причиной?

+0

Вы почти никогда не должны бросать указатель на функцию. Приведение возвращаемого значения из 'GetProcAddress' является единственным приемлемым временем. (Чтобы быть ясным, приведение в последней строке кода либо бесполезно, либо неверно). –

ответ

1

Ну, это, вероятно, происходит потому, что dll, которую вы загружаете, скомпилировалось с помощью другого компилятора, возможно, gcc-компилятора.

Если это так, то проблема заключается в том, что окна используют STDCALL, в котором функция вызываемой отвечает за перепрофилирование стек с помощью «retn immed8» инструкции в то время как GCC использует соглашение о вызовах Cdecl, в которой функция вызывающего абонента отвечает за перегруппировку стека, добавляя к нему некоторое значение с помощью простой команды добавления.

Вы можете определить, был ли исполняемый файл скомпилирован с помощью gcc или visual studio с помощью инструмента PEID , или вы можете использовать шестнадцатеричный редактор и искать строки, указывающие на компилятор.

Также вы можете узнать больше о звонящих соглашениях Here.

+1

Соглашения о вызове не зависят от компилятора. Если он отличается, это связано с тем, что одна сторона использует макрос WINAPI, позволяющий stdcall, а другая сторона - нет. –

4

Неверное указание указателя на функцию MYPROC. Эта функция принимает два аргумента, а не один. Вы можете указать из @ 8 части имени, которая говорит, что для значений аргументов требуется 8 байтов пространства стека. Вызов его одним аргументом, 4-байтным указателем, всегда будет дисбалансом стека.

Вам нужно будет исправить вашу декларацию MYPROC.

+0

Предполагая, что это 32-разрядный код, вы правы. И действительно упоминание «ESP» в сообщении об ошибке подтверждает это. –

+0

@BenVoigt: x64 не использует управление именами, поскольку имеет одно соглашение о вызове. Поэтому '@ 8' четко указывает на 32-битный код. –

+0

Другое дело, вы можете (если возможно) рассмотреть возможность преобразования '_DLLAPI_Call1 @ 8' в функцию C с использованием' extern 'C ". У украшенных (C++) функций есть возможность сменить потом по дороге, а переключение на функцию C будет отменять его и заставить его имя оставаться неизменным. – xcdemon05

Смежные вопросы