LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

DLL calling convention mis-match?

Solved!
Go to solution

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?

 

 

0 Kudos
Message 1 of 5
(3,852 Views)
Solution
Accepted by topic author wally_666

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

0 Kudos
Message 2 of 5
(3,847 Views)

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!

 

0 Kudos
Message 3 of 5
(3,840 Views)

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

0 Kudos
Message 4 of 5
(3,832 Views)

 


@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.

 

 

0 Kudos
Message 5 of 5
(3,828 Views)