01-21-2011 01:56 PM
I'm convering an application into a DLL and all seems to work except when I call it from a stub application I get a Non-Fatal Run-Time error "CVI has detected and inconsistency of the run-time stack" dialog box in the debugger when the DLL function returns.
My stub is using the following to load the function:
prototypes:
HINSTANCE hInstSAE;
typedef int(* x_calcSAE)(int, int *, short *, char *, CXP_PARAM *);
x_calcSAECG calcSAE=NULL;
then in main():
hInstSAE = LoadLibrary("SAE.dll");
if(hInstSAE)
calcSAE=(x_calcSAE)GetProcAddress(hInstSAECG, "sae");
my DLL export function is declared:
int DLLEXPORT DLLSTDCALL sae (int N, int *r, short *data, char *ID, CXP_PARAM *Param);
How do I remove the error? It doesn't seem to cause a problem, as if I click continue and make other calls nothing bad happens other than the debugger popup on each return. How can I get a stack dump to see what is setup before the call and upon the return?
Solved! Go to Solution.
01-21-2011 02:41 PM
Hey wally -
My guess is that you need to change your typedef to the following:
typedef int (*DLLSTDCALL x_calcSAE)(int, int *, short *, char *, CXP_PARAM *);
Generally, the default calling convention used by CVI is __cdecl, which does not match your function prototype's calling convention of __stdcall. This means if you do not specify a calling convention for your function pointer, the __cdecl calling convention will be used. You must update the function pointer type to match the declared function prototype.
NickB
National Instruments
01-21-2011 02:59 PM
That was the first thing I tried, but then I got:
41, 79 Warning: Calling conventions have no effect on variables; calling convention ignored. The position of the calling convention modifier may be incorrect.
But permuting the position of the DLLSTDCALL to:
typedef int DLLSTDCALL (* x_calcSAECG)(int, int *, short *, char *, CXP_PARAM *);
seems to work. Pragmatically its "the solution" but I'd perfer a better understanding of the syntax beyond putzing around until the compiler stops complaining 🙂
I was testing this permutation to see if the error dialog poped up or not when the Email about your replay came it.
Thanks!
01-21-2011 03:50 PM
Hmm... in CVI 2009/2010, I'm able to put the calling convention (DLLSTDCALL) immediately after the return type, immediately before the asterisk, or immediately after the asterisk without any compile warnings. Did you perhaps also include the DLLEXPORT macro in your typedef?
NickB
National Instruments
01-21-2011 04:17 PM
@nickb wrote:
Did you perhaps also include the DLLEXPORT macro in your typedef?
NickB
National Instruments
This is the exact syntax that is working (CVI 8.51):
In program module containing main(): typedef int DLLSTDCALL (* x_calcSAE)(int, int *, short *, char *, CXP_PARAM *); x_calcSAECG calcSAE=NULL; and in main(): hInstSAE = LoadLibrary("SAE.dll"); if(hInstSAE){ calcSAE=(x_calcSAE)GetProcAddress(hInstSAE, "sae"); in the DLL: int DLLSTDCALL sae (int N, int *r, short *data, char *ID, CXP_PARAM *Param)
{
....
}
and its header: int DLLEXPORT DLLSTDCALL sae (int N, int *r, short *data, char *ID, CXP_PARAM *Param);
Some of the finer points of C declarations are pretty poorly documented and quite difficult to make sense of. One that always drives me bonkers is:
void foo( short *raw) { short (*data)[16]; data=(short (*)[16])raw;
value=data[index][channel] }
To take data from an 16 channel A/D card as a raw buffer and then index it by sample number to find certain time regions in the data.