g++ cdecl calling convention with Steinberg VST SDK

5.4k views Asked by At

As far as I have researched, I see that GNU C by default uses cdecl for function calls. The VST SDK explicitly defines the calls as cdecl when compiling with GNU C, and it spits out the following error:

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.

At the same time, when I remove the explicit definition __cdecl, and let the compiler decide, it compiles without a single issue. Should this not throw the same error, because the default is cdecl?

I have read on Wikipedia, that in case of cdecl, "Since GCC version 4.5, the stack must be aligned to a 16-byte boundary when calling a function (previous versions only required a 4-byte alignment.)" Should this provide an insight and probable cause for my problem?

Also I face the same errors when I define that as __fastcall, or __stdcall. So what is really happening here?

2

There are 2 answers

1
Nik Reiman On

I prefer not to modify the source directly, as that gets to be troublesome when trying to maintain multiple platforms. Instead, I pass -D__cdecl="" to the compiler flags to define it away.

I have built a few VST's on linux using this approach, and it works fine. You should be safe just defining away (or manually removing, if you prefer) the explicit __cdecl. The VST SDK is a bit retarded in this sense, especially in that it believes there are only 2 operating systems in the world worth supporting, Mac and Windows. If you look in aeffect.h, you'll find the following code:

#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

So basically, the best way to get around this is to undefine __cdecl away. GCC should compile your code just fine.

0
Loke On

After a lot of research, since I am not so good in C++, I have found out the reason. The __cdecl is an extension of Microsoft Visual C++, and the same can be implemented in GNU C as __attribute__((cdecl)) at the end of a function declaration.

Microsoft VC++ Approach:

void __cdecl MyFunction(int, int);

GNU C++ Approach:

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

None of the above are part of standard C++.

Setting VSTCALLBACK to nothing works, because cdecl is the default calling method in G++.

I do not understand why Steinberg programmers have defined it the way they have done, because I can't find a single instance of VC++ approach implemented in G++ ever. In fact in case of Mac OSX (g++ compiler version is 4.2.1, and on Linux I have 4.6.3), when VSTCALLBACK is set to __cdecl, it fails in a similar manner.