Author Topic: Change Packing Settings?  (Read 2990 times)

0 Members and 1 Guest are viewing this topic.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Change Packing Settings?
« on: November 08, 2019, 04:29:12 pm »
When working with libraries (and especially the Windows API), how we pack our data is essential to transfer data back and forth from our programs to their respective library functions.  A perfect example is the recent windows printer dialog which I just put up.  In it, we need to transfer data back and forth which meets this data requirement:

Code: [Select]
    TYPE PRINTDLGEX
    lStructSize AS _UNSIGNED LONG
    hwndOwner AS _UNSIGNED _OFFSET ' HWND
    hDevMode AS _UNSIGNED _OFFSET ' HGLOBAL
    hDevNames AS _UNSIGNED _OFFSET ' HGLOBAL
    hDC AS _UNSIGNED _OFFSET ' HDC
    Flags AS _UNSIGNED LONG
    Flags2 AS _UNSIGNED LONG
    ExclusionFlags AS _UNSIGNED LONG
    nPageRanges AS _UNSIGNED LONG
    nMaxPageRanges AS _UNSIGNED LONG
    lpPageRanges AS _UNSIGNED _OFFSET ' LPPRINTPAGERANGE
    nMinPage AS _UNSIGNED LONG
    nMaxPage AS _UNSIGNED LONG
    nCopies AS _UNSIGNED LONG
    hInstance AS _UNSIGNED _OFFSET ' HINSTANCE
    lpPrintTemplateName AS _UNSIGNED _OFFSET ' LPCSTR
    lpCallback AS _UNSIGNED _OFFSET ' LPUNKNOWN
    nPropertyPages AS _UNSIGNED LONG
    lphPropertyPages AS _UNSIGNED _OFFSET ' HPROPSHEETPAGE *
    nStartPage AS _UNSIGNED LONG
    dwResultAction AS _UNSIGNED LONG
    END TYPE

In 32-bit windows, this data type is perfectly fine the way it is to work with PrintDlgExA.  In 64-bit windows, it'll glitch out and toss us an error message.

What's the difference?

32-bit windows expects the data to be packed in 4-byte segments.  64-bit windows expects it to be packed in 8-byte segments...  This means we have to toss some padding into the file to manually add extra space onto some of those longs, such as below.

   TYPE PRINTDLGEX
    lStructSize AS _UNSIGNED LONG '4 bytes
    PADDING AS LONG 'we need 4 bytes of padding here, so that we keep our data lined up into 8byte segments properly
    hwndOwner AS _UNSIGNED _OFFSET ' HWND '8 bytes since we're in 64-bit mode, so this is fine.

You guys who are more familiar with coding in C than I am, have probably dealt with this issue much more than I ever had.  At best, I only claim to be an untalented hack when it comes to working with C -- I'm still learning and improving with the language all the time...

My question here is:

Is there some simple way to define how to pack a data structure with use for DECLARE LIBRARY like this? 

If we were to code this in C, we'd use a command similar to one of the following:
Code: [Select]
C++11's alignas(1)
struct __attribute__ ((packed)) BMPHeader
#pragma pack(1)

But how the heck would we do this within QB64 itself?  Is it even possible?  Or do I just got to stick to the basics when dealing with these situations and just manually add in some blank padding where it's needed to maintain the structure, as I did in this case to make it work for me??

Any guidance/advice from you guys who have dealt with these type of issues before can give is greatly appreciated.  Seems to me like there should be some simple way to handle these type of things, but if not, one can always just manually pad the structure themselves when it's needed.  (As long as you can decipher any error messages and come to the realization that that's what the problem is!)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!