PRB: DLL Function Returns Float or Double Value Incorrectly

Last reviewed: July 23, 1997
Article ID: Q86081
3.00 3.10 WINDOWS kbprg kbprb kbcode

The information in this article applies to:

  • Microsoft Windows Software Development Kit (SDK) for Windows versions 3.1 and 3.0

SYMPTOMS

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

CAUSE

The pointer used to return a floating-point result under the C calling convention is invalid once control returns to the application.

RESOLUTION

Declare 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 INFORMATION

The 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 /Zp

HANDLE _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 /Zp

extern 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 /Zp

float _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 /Zp

extern 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
KBCategory: kbprg kbprb kbcode
KBSubcategory: KrFltPt
Keywords : kb16bitonly


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: July 23, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.