views:

841

answers:

2

In xp 32bit this line compiles with not problem however in vista 64bit this line:

m_FuncAddr = ::GetProcAddress (somthing);

gives the following error

error C2440: '=' : cannot convert from 'FARPROC' to 'int (__cdecl *)(void)'

GetProcAddress is defined as

WINBASEAPI FARPROC WINAPI GetProcAddress (somthing)

And m_FuncAddr as

int (WINAPI *m_FuncAddr)();

From what I understand both are stdcall's.

To avoid the error I had to put

m_FuncAddr = (int (__cdecl *)(void))::GetProcAddress(somthing);

My Question:

If both m_FuncAddr and GetProcAddress have the stdcall calling convention why do I have to 'recall' it with cdecl ?

Is it possible that the VS project setting 'default calling convention (which is set to cdecl) over-rides the assignemet statment above ?

Thanks in advanced!

[Edit]

To clerfiy the question:

On one side of the equation (say side 1) i have

int __stdcall * m_FuncAddr

On other side (side 2)

INT_PTR far __stdcall GetProcAddress

So how is it that i have to cast side 2 with cdecl if both are stdcalls ? Or am I not getting something ?

+2  A: 

It's a coincidence that it compiles correctly in 32bit; the correct syntax is:

typedef int (WINAPI *FFuncType)();
FFuncType m_FuncAddr;
m_FuncAddr = (FFuncType)::GetProcAddress (somthing);

You need to explicitly cast the result of ::GetProcAddress to the proper function signature. In 32bit, FARPROC happens to work with the signature you have, but probably not in 64bit.

Edit: Yes, in fact, looking at windef.h, the return type is INT_PTR in 64bit, so that's why you got the compiler error. You will still need to cast to the function signature as above for any function which does not happen to match the placeholder for FARPROC, though, so you should be doing it as above in general.

Nick
But the thing i that FFuncType is stdcall and im casting it to cdecl, or am i not getting somthing ?
Roman M
Remember that int is 32-bit even in 64-bit builds.
Adam Mitz
The calling convention may be DLL-specific, so the only "safe" way is to cast to the header-defined typedef. It may be that all DLL's use the same convention, but I don't know that for a fact.
Nick
The calling convention matches, it's WINAPI on both sides. The problem is that the return type doesn't match (see my answer).
Adam Mitz
int vs INT_PTR ?usually that just gives a warrning ... ?
Roman M
Just replace INT_PTR with __int64 and you'll see the problem right away. Do you really want to truncate those function pointers to 32-bit?
Adam Mitz
In your "edit" section you still claim that he should be "doing it as above"... but above uses an "int" as the return type of FFuncType, which is the problem in the first place.
Adam Mitz
That's not the problem though; that just masks the problem. The real issue is that you need to typedef and cast to the actual function signature being exported from the DLL, not use the placeholder signature returned from ::GetProcAddess.
Nick
The problem is being exposed because the definition for FARPROC changed, but that's just a placeholder which happened to match before. The real fix is not not rely on implicitly matching the placeholder.
Nick
+3  A: 

The return type should be INT_PTR (a 64-bit value in 64-bit builds). You shouldn't cast around this error -- the compiler is trying to tell you that something is wrong.

From WinDef.h:

#ifdef _WIN64
typedef INT_PTR (FAR WINAPI *FARPROC)();

So the declaration of m_FuncAddr should be:

INT_PTR (WINAPI *m_FuncAddr)();
Adam Mitz
Adam your answer is right but please edit it a little, one useful thing i found is this error didnt really have to do with calling conventions like i initially tought. All i did is to change m_FuncAddr return type to INT_PTR and problem solved itself. So please make your answer more complete.
Roman M
Edited... let me know if it's still not clear.
Adam Mitz