c++ - MSVC 和 gcc 之间的调用约定

标签 c++ visual-c++ gcc calling-convention

我有一个用 MSVC 构建的程序,它正在动态加载一个 dll。 dll 提供了一个从主程序调用的函数。如果两者都是使用 MSVC 或 gcc 构建的,一切都很好,但是当我编译时,例如MSVC 的 main 和 gcc 的 dll 出了点问题。

#  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;
}

问题是,调用目标之后是而不是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

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

最佳答案

在这种情况下,调用约定毫无意义。问题是 vtable 布局之类的东西。 MSVC ABI 和 Itanium 在很多事情上存在分歧。除非明确支持,否则您不能编译 C++ 接口(interface)并在编译器之间混合和匹配。如果设置正确,Clang 和 G++ 应该可以互操作,而 Clang 和 MSVC 可能可以互操作,具体取决于您使用的具体功能。

一般来说,不要为 C++ 接口(interface)混合搭配 C++ 编译器。这是行不通的。

关于c++ - MSVC 和 gcc 之间的调用约定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31950743/

相关文章:

c++ - 在 C++ 中创建 MakeFile

c - xCode 产生 "Undefined symbols for architecture x86_64"错误,而 gcc 编译没有错误

c++ - 将左值与抽象类一起使用

c++ - 在这种情况下如何保持良好的数据封装?

c++ - 为什么某些编译器拒绝作为指针传递的匿名对象?

c++ - MSVC 的标准库没有为 std::string、std::shared_ptr 等定义飞船操作符?

c++ - 有什么理由反对在 QueryInterface() 实现中直接调用 AddRef() 吗?

c# - 找不到 PInvoke DLL - BUG?

C: gcc 中的 uint16_t 减法行为

c - 结构中的零长度数组有何用处?