64-битные — 64-битные функции передачи C ++ с «разными» соглашения о вызовах в качестве параметров дают неоднозначную ошибку

Моя цель — легко извлечь прототип произвольной функции с соглашениями о вызовах __cdecl и __stdcall. Он отлично работает в 32-битной. Единственное, что меняется, это соглашение о вызовах в параметрах моей функции шаблона.

В соответствии с Википедия:
«При компиляции для архитектуры x64 в контексте Windows (с использованием инструментов Microsoft или сторонних разработчиков) существует только одно соглашение о вызовах — описанное здесь, так что теперь все stdcall, thiscall, cdecl, fastcall и т.д. одно и то же.»

Это нарушает мой код в 64-битном. Несмотря на то, что соглашения о вызовах одинаковы, передача функций в качестве параметра по-прежнему требует правильной номенклатуры. И.Е. если функция определена как __stdcall, вы должны передать ее в оболочку, которая принимает __stdcall. Даже если __cdecl идентичен, вы все равно должны передать функции, определенные как __cdecl, в оболочку, которая принимает __cdecl.

Пример, который работает в 32-разрядной версии:

template<typename T, typename... Args>
struct WrapperSTD { typedef T(__stdcall *Functor)(Args...); };

template<typename T, typename... Args>
struct WrapperC { typedef T(*Functor)(Args...); };

template<typename T, typename... Args>
WrapperSTD<T, Args...> wrap(T(__stdcall *func)(Args...)) {
return WrapperSTD<T, Args...>{};
}
template<typename T, typename... Args>
WrapperC<T, Args...> wrap(T(*func)(Args...)) {
return WrapperC<T, Args...>{};
}

Моей целью было уметь бегать, например:

using MsgBoxProto = decltype(wrap(MessageBoxA))::Functor;

Это хорошо для 32-разрядных. Однако, поскольку __stdcall и __cdecl, по-видимому, идентичны в x64, он не будет работать в 64-битной среде и выдает ошибку, сообщающую, что вызовы являются неоднозначными. Это также говорит мне, что шаблон уже был определен. Интуитивно кажется, что я мог бы передавать функции с __cdecl в эту функцию __stdcall, так как компилятор видит их как идентичные. Однако это не работает:

template<typename T, typename... Args>
struct WrapperFC { typedef T(__stdcall *Functor)(Args...); };

template<typename T, typename... Args>
WrapperFC<T, Args...> wrap(T(__stdcall *func)(Args...)) {
return WrapperFC<T, Args...>{}; // same as below
}

template<typename T, typename... Args>
WrapperFC<T, Args...> wrap(T(__cdecl *func)(Args...)) {
return WrapperFC<T, Args...>{}; // same as above
}

Ошибка C2995 «WrapperFC wrap (T (__cdecl *) (Args …))»: шаблон функции уже определен

Если я оставлю только одну из них, я не смогу обернуть обе эти функции одновременно:

void __cdecl foo(int i){}
void __stdcall bar(int i){}

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

TL; DR:
Если соглашения о вызовах в 64-разрядных архитектурах идентичны, почему я не могу передать одно соглашение о вызовах в функцию, которая ожидает другое? И как я могу это исправить?

6

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector