27
float __stdcall (*pFunc)(float a, float b) = (float (__stdcall *)(float,float))0x411280;

How to declare a function pointer with calling convention? The above gives me an error.

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
Yulo
  • 291
  • 1
  • 3
  • 4

3 Answers3

49

The trick is placing the __stdcall inside the parentheses like this:

float (__stdcall *pFunc)(float a, float b) = (float (__stdcall *)(float,float))0x411280;

Of course, you are recommended to use a typedef instead, but the same trick applies:

typedef float (__stdcall *FuncType)(float a, float b);
zhuman - MSFT
  • 1,028
  • 12
  • 16
namey
  • 695
  • 5
  • 8
1

For a regular function, you can usually do:

__cdecl const int func();
__cdecl const int (func)();
const __cdecl int func();
const int __cdecl func();
const int (__cdecl func)();
__cdecl const __cdecl int (__cdecl func)();

It is implementation defined whether or not a compiler will accept all of these forms. Clang does. To me, the 5th version makes the most semantic sense, because it is a property of the function and not the return type alone.

You can do all of this with __attribute__((cdecl)) instead of __cdecl, which can also be used after the function, unlike __cdecl

const int (__cdecl func)() __attribute__((cdecl));

Now, to declare a constant pointer pfunc to a function with a specific calling convention:

__cdecl const int (*const pfunc)();
const __cdecl int (*const pfunc)();
const int __cdecl (*const pfunc)();
const int (__cdecl *const pfunc)();
const int (*const __cdecl pfunc)();
const int (*__cdecl const pfunc)();
__cdecl const __cdecl int (__cdecl *const pfunc)();
const int (*const pfunc)() __attribute__((cdecl));

Note that const has to be after the asterisk as usual. With double function pointers, the pointers can go anywhere with respect to the calling convention, but you have to put it in the correct place with respect to const.

Again, it is implementation defined as to what form a compiler accepts. Clang accepts all forms and correctly interprets them as the type const int (*const)() __attribute__((cdecl))

Lewis Kelsey
  • 4,129
  • 1
  • 32
  • 42
  • 1
    I've tried every single combination of the above to try to get the GCC compiler to recognise a function pointer typedef that specifies the __cdecl calling convention, For example: `typedef void* (__cdecl *byte_array_alloc_fn)(int count)` which compiles using MSVC, but produces errors in GCC. – Tim Calladene Aug 26 '22 at 08:53
  • @TimCalladene off the top of my head I would assume that it's because it does nothing in x64 code: https://stackoverflow.com/a/66403563/7194773 (on MSVC it appears to override the /Gv compiler option if enabled. Also, you have to use `__attribute__((cdecl))` on gcc – Lewis Kelsey Oct 22 '22 at 14:36
0

__fastcall is the optimized one (fastest calling convention) but not used for an unknown reason

Try:

int (__fastcall *myfunction)(int,float);
crthompson
  • 15,653
  • 6
  • 58
  • 80
Mandrake
  • 363
  • 1
  • 3
  • 11
  • You should have had a look at what these unknown reasons are before posting, and eventually asked a new question if it hadn't already been asked. This site is supposed to be about sharing knowledge, not suppositions. – Johan Boulé Jul 08 '18 at 16:58