PRB: DLL Function Returns Float or Double Value IncorrectlyLast reviewed: July 23, 1997Article ID: Q86081 |
3.00 3.10
WINDOWS
kbprg kbprb kbcode
The information in this article applies to:
SYMPTOMSWhen a function using the C calling convention and exported from a dynamic- link library (DLL) returns a data value of type float, double, or long double, the calling application receives unexpected values.
CAUSEThe pointer used to return a floating-point result under the C calling convention is invalid once control returns to the application.
RESOLUTIONDeclare the DLL function using the Pascal calling convention or allocate memory from the global heap to hold the floating-point result and return the handle from the DLL function.
MORE INFORMATIONThe DLL and any application that calls the DLL each have separate floating-point accumulators. When an application calls a DLL function declared with the Pascal calling convention, the application allocates space on the stack to receive the returned data type. The DLL function pushes the value onto the stack for the application to use. When an application calls a DLL function that uses the C calling convention, no stack space is allocated because the calling function cleans up the stack. Under the C calling convention, the DLL function returns a pointer (in DX:AX) to the floating-point accumulator, which contains the result. However, once the application regains control, the pointer is not valid. The code examples below demonstrate returning a float value under the C and Pascal calling conventions:
C Calling Convention
// C calling convention - DLL // Compile options required: /Asw /G2sw /ZpHANDLE _far floatcalc(float fl1, float fl2); HANDLE _far floatcalc(float fl1, float fl2) { HANDLE hFloat; float _far *pFloat; hFloat = GlobalAlloc(GMEM_MOVEABLE, sizeof(float)); pFloat = (float _far *)GlobalLock(hFloat); *pFloat = fl1 * fl2; GlobalUnlock(hFloat); return hFloat;}
// C calling convention - Application // Compile options required: /AS /G2sw /Zpextern HANDLE _far floatcalc(float fl1, float fl2);
void Calc(void){ float _far *pFloat, fl; HANDLE lFloat; lFloat = floatcalc((float)3.0, (float)4.1); // Call DLL function pFloat = (float _far *)GlobalLock(lFloat); fl = *pFloat; GlobalFree(lFloat);}
Pascal Calling Convention
// Pascal calling convention - DLL // Compile options required: /Asw /G2sw /Zpfloat _far _pascal FloatCalc(float fl1, float fl2); float _far _pascal FloatCalc(float fl1, float fl2) { return fl1 * fl2; }
// Pascal calling convention - Application // Compile options required: /G2sw /Zpextern float _far _pascal FloatCalc(float fl1, float fl2);
void Calc(void){ float temp; temp = FloatCalc((float)3.1, (float)4.2); // Call DLL function}
|
Additional reference words: 3.00 3.10
© 1998 Microsoft Corporation. All rights reserved. Terms of Use. |