В xp 32bit эта строка компилируется без проблем, но в Vista 64bit эта строка:
m_FuncAddr = ::GetProcAddress (somthing);
дает следующую ошибку
error C2440: '=' : cannot convert from 'FARPROC' to 'int (__cdecl *)(void)'
GetProcAddress определяется как
WINBASEAPI FARPROC WINAPI GetProcAddress (somthing)
И m_FuncAddr как
int (WINAPI *m_FuncAddr)();
Насколько я понимаю, оба являются стандартными вызовами.
Чтобы избежать ошибки, мне пришлось поставить
m_FuncAddr = (int (__cdecl *)(void))::GetProcAddress(somthing);
Мой вопрос:
Если и m_FuncAddr, и GetProcAddress имеют соглашение о вызовах stdcall, почему мне нужно «отозвать» его с помощью cdecl?
Возможно ли, что соглашение о вызовах по умолчанию для настройки проекта VS (для которого установлено значение cdecl) отменяет указанное выше положение assignemet?
Заранее спасибо!
[Редактировать]
Чтобы ответить на вопрос:
На одной стороне уравнения (скажем, на стороне 1) у меня есть
int __stdcall * m_FuncAddr
С другой стороны (сторона 2)
INT_PTR far __stdcall GetProcAddress
Так как же мне нужно передать сторону 2 с помощью cdecl, если оба являются стандартными вызовами? Или я чего-то не понимаю?
Если вы проверяете только вкладку «ответы», см. Мои изменения ниже.





Это совпадение, что он правильно компилируется в 32-битной версии; правильный синтаксис:
typedef int (WINAPI *FFuncType)();
FFuncType m_FuncAddr;
m_FuncAddr = (FFuncType)::GetProcAddress (somthing);
Вам необходимо явно привести результат :: GetProcAddress к правильной сигнатуре функции. В 32-битной версии FARPROC работает с вашей подписью, но, вероятно, не в 64-битной.
Обновлено: Да, на самом деле, глядя на windef.h, тип возвращаемого значения - INT_PTR в 64-битной версии, поэтому вы получили ошибку компилятора. Тем не менее, вам все равно нужно будет выполнить приведение к сигнатуре функции, как указано выше, для любой функции, которая не соответствует заполнителю для FARPROC, поэтому в целом вы должны делать это, как указано выше.
Но дело в том, что FFuncType - это stdcall, и я привожу его к cdecl, или я что-то не получаю?
Помните, что int 32-битный даже в 64-битных сборках.
Соглашение о вызовах может быть специфичным для DLL, поэтому единственный «безопасный» способ - это приведение к определенному в заголовке typedef. Возможно, все библиотеки DLL используют одно и то же соглашение, но я не знаю этого наверняка.
Соглашение о вызовах совпадает, это WINAPI с обеих сторон. Проблема в том, что возвращаемый тип не совпадает (см. Мой ответ).
int против INT_PTR? обычно это просто предупреждение ...?
Просто замените INT_PTR на __int64, и вы сразу увидите проблему. Вы действительно хотите усечь эти указатели на функции до 32-битных?
В разделе «редактирования» вы по-прежнему утверждаете, что он должен «делать это, как указано выше» ... но выше в качестве возвращаемого типа FFuncType используется «int», что является проблемой в первую очередь.
Но проблема не в этом; это просто маскирует проблему. Реальная проблема заключается в том, что вам нужно ввести typedef и привести к фактической сигнатуре функции, экспортируемой из DLL, а не использовать подпись заполнителя, возвращаемую из :: GetProcAddess.
Проблема обнаруживается, потому что определение FARPROC изменилось, но это просто заполнитель, который совпадал раньше. Настоящее исправление не зависит от неявного соответствия заполнителю.
Тип возврата должен быть INT_PTR (64-битное значение в 64-битных сборках). Вы не должны обходить эту ошибку - компилятор пытается сказать вам, что что-то не так.
Из WinDef.h:
#ifdef _WIN64
typedef INT_PTR (FAR WINAPI *FARPROC)();
Итак, объявление m_FuncAddr должно быть:
INT_PTR (WINAPI *m_FuncAddr)();
Адам, ваш ответ правильный, но, пожалуйста, отредактируйте его немного, я обнаружил одну полезную вещь: эта ошибка на самом деле не имеет отношения к соглашениям о вызовах, как я изначально думал. Все, что я сделал, это изменил тип возвращаемого значения m_FuncAddr на INT_PTR, и проблема решилась сама собой. Поэтому, пожалуйста, сделайте свой ответ более полным.
Мой ответ все еще остается в силе после вашего редактирования, int и INT_PTR сильно отличаются в 64-битных сборках!