问题:
1:DLL导出函数该用哪种调用约定?大部分看到的都是WINAPI,也就是__stdcall,但好像用__cdecl也能导出,用起来好像也没发现问题
这两种约定,无非就是谁负责清理栈的问题,理论上,如果导出的dll函数调用约定不一致,调用时就会产生栈不一至的问题,可我在实际用时默认都是__cdecl,好像也没发现异常2.该使用def文件定义导出函数,还是使用 extern "C" __declspec (dllexport) 定义导出函数?使用def文件定义导出函数的好处是使名字绝对正确
而使用extern "C" __declspec (dllexport)定义导出函数时,如果是__stdcall调用约定,导出函数名前面会被加上下画线,如果要保证函数是__stdcall,而且名字又不被修改,难道只能使用def文件?

解决方案 »

  1.   

    1、使用 WINAPI/__stdcall 与 __cdecl 的区别在于,WINAPI 的情况下,函数在返回的时候自动把栈恢复;__cdecl 的函数是调用方负责恢复栈;两个都可以,如果想方便多语言调用呢,使用 WINAPI;2、__declspec(dllexport) 本身就可以输出函数;extern "C" 代表输出函数的名称按照 C 语言的输出方式;.def 的优势是,对于 WINAPI/__stdcall 形式的输出接口,输出名称就是函数名称,不会发生变化。(不会加下划线之类的)如果要保证函数是__stdcall,而且名字又不被修改,只能使用 def 文件。
      

  2.   

    因为现在的编译器会使用leave指令清栈,所以才会出现你说的__stdcall与__cdecl某些情况下不会引发异常的特例。如果使用i386指令集,则无leave指令,__stdcall与__cdecl的调用不一致将必然导致错误。
      

  3.   

    这句是关键.
    加不加extern "C"导出函数,然后用depends查看函数名有什么区别.
    __cdecl跟__stdcall没什么关系,只是在你需要用的时候声明必须对应上.
      

  4.   

    leave只保证函数内部栈平衡,跟__cdecl, __stdcall扯毛关系.
    那个"异常"也只是vc检测栈.
      

  5.   

    extern "C"只是保证不被C++编译器改名,但C编译器也是有“改名”的传统,可以看下4种组合:extern "C" __declspec(dllexport)  int __stdcall  Func(char* p)
    生成的是 _Func@4__declspec(dllexport)  int __stdcall  Func(char* p)
    生成的是 ?Func@@YGHPAD@Z
    extern "C" __declspec(dllexport)  int __cdecl Func(char* p)
    生成的是 Func__declspec(dllexport)  int __cdecl Func(char* p)
    生成的是 ?Func@@YGHPAD@Z
    extern "C" __declspec(dllexport) 要想名字保持原样,只能跟__cdecl配合