将函数分配给具有相同签名的std :: function,但不同的调用约定失败

时间:2013-01-31 13:01:10

标签: c++ mingw std-function stdcall cdecl

以下编译并使用mingw 4.7.2和-m64标志运行。

但是使用-m32或任何mingw 32位版本它无法编译。它是一个错误还是我错过了编译器标志?

    #include <iostream>
    #include <functional>

    using namespace std;

    int __cdecl ccall(int i)
    {
        cout << i << endl;
        return 0;
    }

    int __stdcall stdcall(int i)
    {
        cout << i << endl;
        return 0;
    }

    int __fastcall fastcall(int i)
    {
        cout << i << endl;
        return 0;
    }


    int main() {

        std::function<int(int)> fnc = ccall;
        fnc(10);

        std::function<int(int)> fnstd = stdcall;
        fnstd(100);

        std::function<int(int)> fnfast = fastcall;
        fnfast(200);

        return 0;
    }

错误消息:

    ...\Local\Temp\cc4ekW9J.s: Assembler messages:
    ...\Local\Temp\cc4ekW9J.s:30: Error: symbol `__ZNSt17_Function_handlerIFiiEPFiiEE9_M_invokeERKSt9_Any_datai' is already defined 
    ...\Local\Temp\cc4ekW9J.s:80: Error: symbol `__ZNSt14_Function_base13_Base_managerIPFiiEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation' is already defined
    ...\Local\Temp\cc4ekW9J.s:114: Error: symbol `__ZNSt14_Function_base13_Base_managerIPFiiEE10_M_managerERSt9_Any_dataRKS4_St18_Manager_operation' is already defined

我在lambda函数中“隐藏”调用后,最终以这种方式完成它,它运行得很好:

    template<class Ret, class... Args> class StdCall
    {
    public:
        typedef Ret(__stdcall Fn_t)(Args...);
        typedef std::function<Ret (Args...)> Functor_t;
        Functor_t get(Fn_t pFn)
        {
            return [pFn](Args... as){
                return pFn(as...);
            };
        }
    };

    auto fn1 = CdeclCall<int,int>().get( ccall );
    auto fn2 = StdCall<int,int>().get( stdcall );

    fn1(123);
    fn2(156);

1 个答案:

答案 0 :(得分:0)

算你自己很幸运。想想用错误的调用约定可能导致函数调用的那种破坏!哦,只需使用“正确”调用约定创建一个shim函数,该约定调用“错误”调用。也许你可以在一个单独编译的文件中隐藏它。