【问题标题】:g++ cdecl calling convention with Steinberg VST SDK使用 Steinberg VST SDK 的 g++ cdecl 调用约定
【发布时间】:2012-05-28 18:31:31
【问题描述】:

据我研究,我发现 GNU C 默认使用 cdecl 进行函数调用。使用 GNU C 编译时,VST SDK 将调用明确定义为 cdecl,并吐出以下错误:

again.cpp:27:15: warning: multi-character character constant [-Wmultichar]
In file included from /code/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.h:16:0,
             from /code/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.h:17,
             from again.h:16,
             from again.cpp:13:
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:125:32: error: expected ')' before '*' token
In file included from /code/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.h:16:0,
             from /code/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.h:17,
             from again.h:16,
             from again.cpp:13:
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:126:32: error: expected ')' before '*' token
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:127:27: error: expected ')' before '*' token
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:128:27: error: expected ')' before '*' token
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:129:27: error: expected ')' before '*' token
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:130:28: error: expected ')' before '*' token
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:149:2: error: 'AEffectDispatcherProc' does not name a type
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:152:2: error: 'AEffectProcessProc' does not name a type
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:155:2: error: 'AEffectSetParameterProc' does not name a type
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:158:2: error: 'AEffectGetParameterProc' does not name a type
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:183:2: error: 'AEffectProcessProc' does not name a type
/code/vstsdk2.4/pluginterfaces/vst2.x/aeffect.h:187:2: error: 'AEffectProcessDoubleProc' does not name a type
In file included from /code/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.h:17:0,
             from again.h:16,
             from again.cpp:13:
/code/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.h:27:35: error: expected ')' before 'audioMaster'
In file included from /code/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.h:17:0,
             from again.h:16,
             from again.cpp:13:
/code/vstsdk2.4/public.sdk/source/vst2.x/audioeffect.h:155:2: error: 'audioMasterCallback' does not name a type
In file included from again.h:16:0,
             from again.cpp:13:
/code/vstsdk2.4/public.sdk/source/vst2.x/audioeffectx.h:27:36: error: expected ')' before 'audioMaster'
In file included from again.cpp:13:0:
again.h:22:29: error: expected ')' before 'audioMaster'
again.cpp:16:36: error: 'audioMasterCallback' was not declared in this scope
again.cpp:17:1: error: expected ',' or ';' before '{' token
again.cpp:22:14: error: expected constructor, destructor, or type conversion before '(' token
scons: *** [again.os] Error 1
scons: building terminated because of errors.

同时,当我删除显式定义 __cdecl 并让编译器决定时,它编译时没有任何问题。这不应该抛出同样的错误吗,因为默认是 cdecl?

我在 Wikipedia 上读到,对于 cdecl,“从 GCC 版本 4.5 开始,调用函数时堆栈必须与 16 字节边界对齐(以前的版本只需要 4 字节对齐。)”应该这为我的问题提供了洞察力和可能的原因?

当我将它定义为 __fastcall 或 __stdcall 时,我也会遇到同样的错误。那么这里到底发生了什么?

【问题讨论】:

    标签: linux g++ vst cdecl


    【解决方案1】:

    我不喜欢直接修改源代码,因为在尝试维护多个平台时会很麻烦。相反,我将-D__cdecl="" 传递给编译器标志来定义它。

    我已经使用这种方法在 linux 上构建了一些 VST,并且效果很好。您应该安全地定义(或手动删除,如果您愿意)显式 __cdecl。 VST SDK 在这个意义上有点迟钝,特别是它认为世界上只有 2 个操作系统值得支持,Mac 和 Windows。如果你查看aeffect.h,你会发现以下代码:

    #if TARGET_API_MAC_CARBON
        #ifdef __LP64__
            #pragma options align=power
        #else
            #pragma options align=mac68k
        #endif
        #define VSTCALLBACK
    #elif defined __BORLANDC__
        #pragma -a8
    #elif defined(__GNUC__)
        #pragma pack(push,8)
        #define VSTCALLBACK __cdecl
    #elif defined(WIN32) || defined(__FLAT__) || defined CBUILDER
        #pragma pack(push)
        #pragma pack(8)
        #define VSTCALLBACK __cdecl
    #else
        #define VSTCALLBACK
    #endif
    

    所以基本上,解决这个问题的最好方法是取消定义 __cdecl。 GCC 应该可以很好地编译您的代码。

    【讨论】:

    • 您好 Nik,我了解您的方法,但我正在尝试了解原因。毕竟,为什么它对所有方法都抛出相同的错误,即 cdecl、fastcall、stdcall?
    【解决方案2】:

    经过大量研究,由于我的 C++ 不太好,我找到了原因。 __cdecl 是 Microsoft Visual C++ 的扩展,在 GNU C 中可以像函数声明末尾的 __attribute__((cdecl)) 一样实现。

    微软 VC++ 方法:

    void __cdecl MyFunction(int, int);
    

    GNU C++ 方法:

    void MyFunction(int, int) __attribute__((cdecl));
    

    以上都不是标准 C++ 的一部分。

    将 VSTCALLBACK 设置为空有效,因为 cdecl 是 G++ 中的默认调用方法。

    我不明白为什么 Steinberg 程序员会按照他们的方式定义它,因为我找不到任何一个用 G++ 实现的 VC++ 方法实例。事实上,在 Mac OSX 的情况下(g++ 编译器版本是 4.2.1,在 Linux 上我有 4.6.3),当 VSTCALLBACK 设置为 __cdecl 时,它会以类似的方式失败。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 2015-04-16
      • 2023-03-28
      • 1970-01-01
      • 2023-03-21
      • 2011-07-06
      • 1970-01-01
      相关资源
      最近更新 更多