调用MSVC和gcc之间的约定

use*_*087 1 c++ gcc calling-convention visual-c++

我有一个程序生成与MSVC动态加载DLL.dll提供从主程序调用的函数.如果两者都使用MSVC或gcc构建,一切都很好,但是当我编译例如main与MSVC和dll与gcc的东西是错误的.

#  ifdef __GNUC__
#    define CDECL __attribute__ ((__cdecl__))
#  else
#    define CDECL __cdecl
#  endif

struct EXP result {
    uint32_t code;
};

#define SUCCESS result{0};

virtual result CDECL foo(char const* const*& target) const {
    target = (char const* const*)0xAFFE;
    return SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

问题是,在调用目标为零而不是0xAFFE之后.主程序使用__cdecl调用约定编译.结构被打包(没有对齐),但我也尝试对齐不同的大小(1,2,4,8,16).我也尝试使用__declspec/__atribute__(dllexport)两种变体的不同组合.

如果我查看汇编代码,有两个很大的区别:

; MSVC                          |   gcc
;===============================|================================
; before calling                |
;-------------------------------|--------------------------------
                                |   sub     dword ptr [esp+4],8
                                |
; foo();                        |
;-------------------------------|--------------------------------
push    ebp                     |   push    ebp
mov     ebp,esp                 |   mov     ebp,esp
mov     eax,dword ptr [target]  |   
mov     dword ptr [eax],0AFFEh  |   
mov     eax,dword ptr [ebp+0Ch] |   mov     eax,dword ptr [ebp+0Ch]
mov     dword ptr [eax],0       |   mov     dword ptr [eax],0AFFEh
                                |   mov     eax,0
pop     ebp                     |   pop     ebp
ret                             |   ret
Run Code Online (Sandbox Code Playgroud)

即使我在两个编译器上使用相同的调用约定,为什么会这样?我该如何解决?

Pup*_*ppy 6

在这种情况下,调用约定毫无意义.问题是像vtable布局这样的东西.MSVC ABI和Itanium对很多事情都持不同意见.除非明确支持,否则无法编译C++接口并在编译器之间进行混合和匹配.如果设置正确的设置,Clang和G ++应该是可互操作的,并且Clang和MSVC可以互操作,具体取决于您使用的确切功能.

一般来说,不要混用和匹配C++接口的C++编译器.它不会起作用.