Stdcall переопределен визуальной студией?

В 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, если оба являются стандартными вызовами? Или я чего-то не понимаю?

Мой ответ все еще остается в силе после вашего редактирования, int и INT_PTR сильно отличаются в 64-битных сборках!

Adam Mitz 17.10.2008 05:53

Если вы проверяете только вкладку «ответы», см. Мои изменения ниже.

Adam Mitz 21.10.2008 05:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
2
3 564
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это совпадение, что он правильно компилируется в 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, или я что-то не получаю?

RomanM 17.10.2008 05:41

Помните, что int 32-битный даже в 64-битных сборках.

Adam Mitz 17.10.2008 05:42

Соглашение о вызовах может быть специфичным для DLL, поэтому единственный «безопасный» способ - это приведение к определенному в заголовке typedef. Возможно, все библиотеки DLL используют одно и то же соглашение, но я не знаю этого наверняка.

Nick 17.10.2008 05:46

Соглашение о вызовах совпадает, это WINAPI с обеих сторон. Проблема в том, что возвращаемый тип не совпадает (см. Мой ответ).

Adam Mitz 17.10.2008 05:50

int против INT_PTR? обычно это просто предупреждение ...?

RomanM 17.10.2008 05:52

Просто замените INT_PTR на __int64, и вы сразу увидите проблему. Вы действительно хотите усечь эти указатели на функции до 32-битных?

Adam Mitz 17.10.2008 05:58

В разделе «редактирования» вы по-прежнему утверждаете, что он должен «делать это, как указано выше» ... но выше в качестве возвращаемого типа FFuncType используется «int», что является проблемой в первую очередь.

Adam Mitz 17.10.2008 06:18

Но проблема не в этом; это просто маскирует проблему. Реальная проблема заключается в том, что вам нужно ввести typedef и привести к фактической сигнатуре функции, экспортируемой из DLL, а не использовать подпись заполнителя, возвращаемую из :: GetProcAddess.

Nick 17.10.2008 06:28

Проблема обнаруживается, потому что определение FARPROC изменилось, но это просто заполнитель, который совпадал раньше. Настоящее исправление не зависит от неявного соответствия заполнителю.

Nick 17.10.2008 06:31
Ответ принят как подходящий

Тип возврата должен быть 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, и проблема решилась сама собой. Поэтому, пожалуйста, сделайте свой ответ более полным.

RomanM 17.10.2008 06:04

Другие вопросы по теме