views:

33

answers:

1

I'm passing a simple user-defined type (UDT) from Visual Basic 6 to a C DLL. It works fine, except for the double data type, which shows up as 0.

C DLL:

#define WIN32_LEAN_AND_MEAN

#include <windows.h>
#include <stdio.h>

typedef struct _UserDefinedType
{
    signed int      Integer;
    unsigned char   Byte;
    float           Float;
    double          Double;
} UserDefinedType;

int __stdcall Initialize ( void );
int __stdcall SetUDT ( UserDefinedType * UDT );

BOOL WINAPI DllMain ( HINSTANCE Instance, DWORD Reason, LPVOID Reserved )
{
    return TRUE;
}

int __stdcall Initialize ( void )
{
    return 1;
}

int __stdcall SetUDT ( UserDefinedType * UDT )
{
    UDT->Byte = 255;
    UDT->Double = 25;
    UDT->Float = 12345.12;
    UDT->Integer = 1;

    return 1;
}

Visual Basic 6 code:

Option Explicit

Private Type UserDefinedType
    lonInteger As Long
    bytByte As Byte
    sinFloat As Single
    dblDouble As Double
End Type

Private Declare Function Initialize Lib "C:\VBCDLL.dll" () As Long
Private Declare Function SetUDT Lib "C:\VBCDLL.dll" (ByRef UDT As UserDefinedType) As Long

Private Sub Form_Load()

    Dim lonReturn As Long, UDT As UserDefinedType

    lonReturn = SetUDT(UDT)

    Debug.Print "VBCDLL.SetUDT() = " & CStr(lonReturn)

    With UDT
        Debug.Print , "Integer:", CStr(.lonInteger)
        Debug.Print , "Byte:", CStr(.bytByte)
        Debug.Print , "Float:", CStr(.sinFloat)
        Debug.Print , "Double:", CStr(.dblDouble)
    End With

End Sub

The output from Visual Basic:

VBCDLL.SetUDT() = 1
              Integer:      1
              Byte:         255
              Float:        12345.12
              Double:       0

As you can see, the double is appearing as 0, when it should be 25.

+3  A: 

VB6's UDTs align doubles at addresses that are multiples of 4. Here's how to contend with that in C:

#pragma pack(push,4)
typedef struct _UserDefinedType 
{ 
    signed int      Integer; 
    unsigned char   Byte; 
    float           Float; 
    double          Double; 
} UserDefinedType;
#pragma pack(pop)
Windows programmer
+1 I'd also suggest looking at the [Microsoft advice](http://vb.mvps.org/tips/vb5dll.asp) on writing C DLLs to be called from VB. Originally released with VB5 but still relevant to VB6. For instance, it mentions that VB6 expects 4-byte packing.
MarkJ
It didn't say I had any answers on here. Anyway, thanks a bunch to both of you (Windows Programmer) for the code and MarkJ for the link. :)
guitar-