Skip to main content
gamedev.net
🔒 Locked

what is __stdcall?

Started by serratemplar 18 replies 1.5k views
Original Post
serratemplar
serratemplar
We''re working with VC++ by the way. msdn.com says it''s a "calling convention used to call Win32 API functions" and it''s used thus... return-type __stdcall function-name(argument-list) and in my bit of research I learned that it is, if not the opposite, different than the "standard calling convention" __cdecl. I''ve read the definitions for the two but I''m not understanding just what their respective usefulness is. I''m currently studying an article discussing resource file use and the load, save, and unload functions it uses for examples are all defined thus: bool __stdcall(* lpLoad)(fstream *, LPRESFILELUMP); Potentially, lpload is a function ptr to a load function that will load a given data lump...so the resource file manager can be updated to work with varying kinds of files. So, what is this __stdcall identifier all about? Any info at all is appreciated; thanks in advance.
ChaoticCanuck
ChaoticCanuck
Here is a link to an article that describes it better than I will on a forum:

link
serratemplar
serratemplar
So, the way I understand it now is, unless I''m going to be integrating inline assembler into my programs, I''ll never need to specify a function as __stdcall, __cdecl, or __fastcall.

I downloaded an assembler tutorial, but I''m leaving that for later in the summer: I have a CS course in assembler and architecure in the fall so I want my own review to be fresh in my mind when I go.

Thanks again.
SiCrane
SiCrane
Or if you''re working with DLLs where the default calling convention was altered. Or you''re working on a project where the default calling convention is stdcall or fastcall and you need to create a vararg function. Or you''re using function pointers to access windows API functions via GetProcAddress(). Or you need to interface properly with MSVC''s atexit() functions.

Fortunately most of the non-DLL situations will simply fail to compile if you don''t use the properly calling convention specification, and most of the the the DLL situations will give you a runtime error that specifically says that there was probably a calling convention mix-up.
S1CA
S1CA
As well as the DLL issues, there are other fairly places where putting the calling convention is important.

One example is when you''re using function pointers - you need to ensure the function pointed to uses the same convention as the function calling through the pointer.

Somewhere this often happens is when you''re using C runtime library functions that require user provided callbacks. If your callback is written in C++ - e.g. the "compare" function passed to the "qsort()" function *must* be declared as __cdecl - which it won''t be if your function is in a C++ file.



Simon O''Connor
Game Programmer &
Microsoft DirectX MVP
Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site
Dredge-Master
Dredge-Master
please note that that link above is only correct for Microsoft compilers.


If you are using Borland or Intel compilers, they have them defined as so:


__msfastcall(ECX,EBX) (ie the same as the Microsoft compiler)

__fastcall(EAX,EBX,ECX)



and even when not using assembly, aslong as your data is 32bits or smaller, it will make your function faster.
Beer - the love catalystgood ol' homepage
hplus0603
hplus0603
There''s also __thiscall, which passes the "this" parameter in ecx.

Anyway, you shouldn''t need to worry about it. Default functions get default calling conventions and linkage, and Windows API functions, that use __stdcall conventions, are already tagged like that in the Windows headers. Only if you do advanced shared library export stuff do you need to worry about this.
enum Bool { True, False, FileNotFound };
serratemplar
serratemplar
Okay... =)

So, the function prototype I previously listed:

bool __stdcall(* lpLoad)(fstream *, LPRESFILELUMP);

which is basically a template, is saying the function that lpLoad points to is to use the "standard calling convention."

I''m going to hazard a shot in the dark and guess that basically all functions in a Visual C++ built app use __stdcall...so I declare dynamically-linked functions with it to make sure?

Thanks again for all the info.
SiCrane
SiCrane
Visual C++ has a project setting to determine the default calling convention of functions. (/Gd, /Gr or /Gz if you want to look up the flags.) The default default calling convention is __cdecl.
serratemplar
serratemplar
Okay. =) So, since I'm not working with assembler, or .dll's, GetProcAddress(), or atexit(), I really don't need to worry about it yet. =) I know so little about assembler anyway; like I said, next fall.

I would like to use .dll's though for my next project, and resource files (which was the entire origin of this post). Look forward to my questions on dlls. =)

Thanks again everyone.

While we're on the topic, what is a "vararg" function?

EDIT: a rather unsightly typo that I couldn't let go.

[edited by - serratemplar on June 5, 2004 11:25:15 PM]
Fruny
Fruny
While we''re on the topic, what is a "vararg" function?

A function taking a variable number of arguments such as printf.


“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
serratemplar
serratemplar
So it''s just a function that''s been overloaded one or more times? Or is there something special about it?
temp_ie_cant_thinkof_name
temp_ie_cant_thinkof_name
Just so I don''t have to start another thread, what calling convention does opengl32.dll use? I''m thinking it''s stdcall b/c I disassembled a few calls and it doesn''t appear that the stack is being cleaned up by the caller. I need to know b/c i''m starting opengl with nasm where the calling conventions aren''t so transparent.
"I study differential and integral calculus in my spare time." -- Karl Marx
Fruny
Fruny
quote:
Original post by temp_ie_cant_thinkof_name
Just so I don''t have to start another thread, what calling convention does opengl32.dll use?


Either check the header file, or look at the way the symbol names are mangled - MSVC mangles differently for each calling convention, check the documentation for details.


“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Fruny
Fruny
quote:
Original post by serratemplar
So it''s just a function that''s been overloaded one or more times? Or is there something special about it?


No, it''s the same single function (there is no overloading in C, and variadic functions are a C concept), but it can accept any number of arguments. There are macros that will let you retrieve them one by one from the stack. The parameter order ensures that the first argument is at the top of the stack, which enables you to use it to figure out exactly how many arguments there are (e.g. printf counts the number of %whatever placeholders there are in the format strings).

As a word of warning before you become overenthusiastic, variadic functions do not digest C++ objects well.


“Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.” — Brian W. Kernighan
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
SiCrane
SiCrane
quote:
Original post by temp_ie_cant_thinkof_name
Just so I don''t have to start another thread, what calling convention does opengl32.dll use?

This isn''t that hard to figure out. If you check the GL.h header with MSVC, you see that all the functions are defined as APIENTRY functions. If you grep the windows headers you can find that APIENTRY is a #define for FAR __stdcall.
temp_ie_cant_thinkof_name
temp_ie_cant_thinkof_name
Wow, that was quick. Thanks for the help. Alas, I have one more quick question. The FAR word in your post SiCrane; does that have any significance in assembly? B/c I beleive a far call is just a call to an offset that''s possibly in another segment so 48 bits are req''d and CS may need to be changed... Or is it something entirely different in MSVC?
"I study differential and integral calculus in my spare time." -- Karl Marx
SiCrane
SiCrane
If you do a grep for FAR in the windows headers, you''ll find that FAR is #defined to be nothing under WIN32. If you happen to be on a non-WIN32 system, FAR may be defined as _far, for example IA64. I''m not an IA64 programmer, so I have no practical experience if this is actually the case.
Dredge-Master
Dredge-Master
LOL, I remember this.

Back in the days of old (non win32) when we had 16bit memory systems we used a thing called dos.

Also we had Win16 (eg win1.1 to win3.1, and windows for work groups - aka nt, and os2 and so on).

Anyway, we could define memory as normal or huge.

Huge was when you wanted an ENOURMOUS amount of data in your stack space.

eg, you can''t stick much data into a 64K block of memory, but back then we had to.
If you wanted more than 64K, you defined it as HUGE.

Now, normally you would have lets say:

char *neardata;
you could set it with malloc();

if you wanted lots of data it was something like
huge char *fardata();
and you created it with farmalloc();

They had defines as NEAR and FAR.
FAR being huge, and NEAR being normal.

Hope that helped.

If not - from borland.
E2022 Array size too large	Compiler error

The declared array is larger than 64K and the ''huge'' keyword was not used.

If you need an array of this size, either use the ''huge'' modifier, like this:

int huge array[70000L]; /* Allocate 140000 bytes */

or dynamically allocate it with farmalloc( ) or farcalloc( ), like this:

int huge *array = (int huge *) farmalloc (sizeof (int) * 70000); ?? Allocate 140,000 bytes

Beer - the love catalystgood ol' homepage
Dredge-Master
Dredge-Master
btw, like inportb and so on, it''s depricated.

farfree
faralloc
farmalloc
farheapcheck
farrealloc
inp
inpw
outp
outpw
inport
inportb
outport
outportb
Beer - the love catalystgood ol' homepage

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.