cancel
Showing results for 
Search instead for 
Did you mean: 

PB 12.6 issue: passing structure to external C++ function

Former Member
0 Kudos

Hello,

I'm just in the phase of migrating applications from PB 12.5.2 5629 to PB 12.6 4011.

My application uses calls of external functions residing in a C++ DLL with passing structures as arguments.

PB structure:

global type s_s7sbsbulk from structure

    boolean     bconn

    long        job

    integer     machine

    integer     silo

    integer     product

    long        setvalue

    long        actvalue

    integer     state

    byte        manual

end type

C++ struct:

#pragma pack(push, r1, 1) 

typedef struct S7SBSBulkData

{

   ULONG  m_lJobID;       // Job-ID

   short  m_sMachine;     // Machine-No. (1 or 2)

   short  m_sSilo;        // Source Silo (1 - 28)

   short  m_sSiloProduct; // product in silo

   ULONG  m_lSetValue;    // Setvalue in kg

   ULONG  m_lActValue;    // Actual values in kg

   short  m_sStatus;      // Silo-Status

   BYTE   m_bManual;      // manual input

} S7SBSBulkData;

// for GUI (Powerbuilder)

typedef struct S7SBSBLData

{

   WORD   bConn;           // Connection

   S7SBSBulkData m_Bulk;   // data of loading machine

} S7SBSBLData;

#pragma pack(pop, r1)   // stack popped


This worked well for years with PB 12.5.2.

After migrating to PB 12.6 it seems that the alignment of the structure elements in PB has changed.

It seems that each long variable starts now on an address that is a multiple of 4.


PB
C++
size
PB 12.5.2 address
PB 12.6 address
C++ address
boolWORD2000
longULONG4242
intshort2686
intshort28108
intshort2101210
longULONG4121612
longULONG4162016
intshort2202420
byteBYTE1222622


Is this a new feature of PB 12.6 or am I missing something?

Thanks

Werner

PS

This mean that I can't migrate migrate the projects to 12.6 without changing the c++ structures.

Accepted Solutions (0)

Answers (5)

Answers (5)

Former Member
0 Kudos

So far, there is still no solution to this problem!


(But: only passed 3 months, since I have reported this issue.)


Still hoping for a solution.

Former Member
0 Kudos

Bummer!  

former_member202249
Active Participant
0 Kudos

Hi All,

The 12.6 EBF with this fix is expected to be posted sometime later this month.  I don't know an exact date as it depends on how QA testing goes and if there are any regressions but it should be soon. 


Pat

former_member202249
Active Participant
0 Kudos


Werner and All,

This issue has been addressed in PWRBLDR126000P_4-71000192.ZIP   EBF 24672: 12.6 SP00 PL04 (build 4058) that is now available for download.

Please see usage notes below.

When you use a structure or structure array as parameters to external function in the older versions of PowerBuilder, the structure member alignment was one byte.  However, the default alignment is 8 bytes on Windows platform, which means that most (if not all) Windows standard APIs use this value to align arguments with structure members. This will cause a mismatch between Windows APIs and PB applications in PB12.5 and earlier versions PowerBuilder. A well adopted solution to this issue was to add some bytes within PowerBuilder structures manually to fill those gaps. Such gap filling can be complex and error-prone if involving complex nested structures. Worse, this solution fails with the introduction of 64bit application development in PB12.6 because the number of bytes you have to fill may be different between 64bit and 32bit applications.  This was the major reason to make this change in PB12.6. With PB 12.6 for Windows API and Visual C++ the default structure member alignment is now 8 bytes. The structure member alignment was changed to 8 bytes in PB126 for both x64 and x32 applications.  This was an intentional change.   Customers can now call Windows API easier and use the same code for both x64 and x32 applications.

Customers can switch to the old behavior in two ways with PB 12.6 build 4058 and above.

1. Check "Use 1-byte structure member alignment in external function" in Tools, System Options, General page (or set UseZp1=1 in [pb] section, pb.ini, the results are same). The effect is global with this setting changed. To make this work at runtime, please remember to deploy your pb.ini file with your application.

2.  Add “progma_pack(1)” external function’s declaration, like this.

FUNCTION int STLAREGIO ( ref struc_kfzrechnerneu struc_kfz ) LIBRARY "KFZ_SS.DLL" alias for "STLAREGIO;Ansi" progma_pack(1)

progma_pack(1) is 1-byte align, progma_pack(8) is 8-bytes align.  In this way, the effect is only for external function that is declared with this alignment.

Patricia Steinhardt
SAP Active Global Support

Former Member
0 Kudos

Do you really name this statement progma_pack?

Which joker came up with that?

Former Member
0 Kudos

I tried option 2 with IDE and with executable. Now it is working fine.

former_member202249
Active Participant
0 Kudos

Glad to hear and thanks for letting us know it worked for you.

Pat

0 Kudos

there is an alternative link to download this EBF?

I would like to test id

tank's

Former Member
0 Kudos

This is one of the many reasons people are glad that Appeon is taking over. Whoever decided to make a major change like this and fail to document it should be fired.

The prior version behavior should be the default action. It should be left up to the developer to decide if the function call needs special bit alignment.

Plus, what the heck is a progma anyway? It should be something that makes actual sense to a PowerBuilder developer like this:  byte_align(8)

arnd_schmidt
Active Contributor
0 Kudos

Yes, it's time to make PB 12.6 EBFs public or to update the PB 12.6 Evaluation version.

Former Member
0 Kudos

Having to deploy pb.ini with applications is a stupid idea. It would be better to have a function you can call in the application object to set global settings like this.

Former Member
0 Kudos

Hi Roland;

  I agree 100% ... a very weird and not well thought out implementation IMHO.  

Regards ... Chris

Former Member
0 Kudos

Hi Arnd;

  An excellent suggestion and observation!

I still maintain the best PB releases to be on at the moment are either 12.1 or 12.5.1 for production.

Regards ... Chris

Former Member
0 Kudos

It's not necessary to deploy pb.ini. Either use the switch in System Options or add the progma_pack(1) statement to the function definition.


The idea to switch the behavior at function level is a good idea, so you can mix old and new behavior.


But you're right, the default should be the same as in PB12.5!


It should also be well documented in the help files.


P.S.

In C/C++ the comparable statement is #pragma pack(1). See https://msdn.microsoft.com/en-us/library/2e70t5y1.aspx.


There is probably someone at SAP, who can not read properly.


FUNCTION Long GetTcpServiceInfoSBSSilo(long iNr, ref s_s7sbssilos data) LIBRARY "HBTCPSTU.DLL" progma_pack(1)

Former Member
0 Kudos

When you build an exe and copy it to an end-user pc, will the app still work? Does the compiler somehow embed the option in the executable?

They should change it to byte_align. Since it is misspelled already and hasn't been added to the documentation the sooner it is changed the better.

Former Member
0 Kudos

Yes, the app works without pb.ini.

They should also allow the values 1, 2, 4, 8, 16, to have the same capabilities as #pragma pack.

Former Member
0 Kudos

Hi Patricia.

I really believe that all that information needs to be referenced somewhere in help files and manuals (which by the way are not available).... Is there any person responsible for powerbuilder documentation, to which we could ask to make the changes to the next bug fix release?

Andreas.

former_member202249
Active Participant
0 Kudos

Andreas,,

I agree with you but as we're in transition to Appeon, I am not sure when the change to the online help or documentation will be included. 

Pat

Former Member
0 Kudos

transition to Appeon .... 

Former Member
0 Kudos

Hopefully the name can be changed before the documentation is updated. What you have now is a misspelling of a C construct. It needs to be something a PowerBuilder developer who has never used C would understand. Either Byte_Align or maybe just Align.

Former Member
0 Kudos

Hi all,

I know this question is "late to the party"  But I'm seeking clarification

Please confirm or correct,

  1. The Progma_pack(1) keyword is ONLY needed when calling legacy external functions using "legacy" byte alignment.  Custom DLLs that were compiled with the pragma_pack 8 directive do not need any special handling when called from PB
  2. When declaring windows platform functions it is NOT necessary to add the keyword to the declaration

Also

What is the behavior if one erroneously adds the progma_pack(1) or uses the INI file method when calling Windows function?

Thanks

Former Member
0 Kudos

I would like to add, progma_pack is a misspelling of the C language compiler directive:

#pragma pack

If SAP actually cared about PowerBuilder, they would have called it something more PB-ish like ByteAlign() and made the default be the behavior that existed before.

Former Member
0 Kudos

I tested this call three ways on a 64 bit EXE deploy

Function FindNextFileW( ( long handle, ref s_finddata findfiledata ) library "kernel32.dll"

Function FindNewtFileW(  ... ) library "kernel32.dll" progma_pack(1)

Function FindNewFileW(  ... ) library "kernel32.dll" progma_pack(8)

From the application view, all three worked equivalently.  There were no errors!

I am concluding that this fix is only for custom DLLs with structure type parameters that cannot be recompile using an 8 bit directive.  Everything else is NOT affected

PS: using build 4098

Former Member
0 Kudos

Great suggestion Roland ... Maybe Appeon can fix that in their 1st release & use a more intuitive compiler directive.  

Former Member
0 Kudos

Hi Yakov;

  FWIW: I use a lot of SDK calls in my frameworks of which many methods calls pass structures. I have had no issues with PB 12.6 on this using the old PB 12.x external function declarations. I should mention though that all my SDK calls in the frameworks for almost a decade now are solely Unicode based.

HTH

Regards ... Chris

0 Kudos

I have the same problem....

Where i can dowload PowerBuilder EBF?

tank's

Angelo

Former Member
0 Kudos

We just facing same issue. On top we have in our structure string and double values. And from the structure we have an array, which we need to fill. Addresses seems to be changed as well.

e.g.

string

double

string

...

In this constallation we get already problems to access the second string in the structure. The old pointer calculation is now pointing to null .

We need also to know, what was changed in PB12.6, was it by intention and what we have to adjust.

former_member202249
Active Participant
0 Kudos

Hi All,


PB engineering has confirmed that this was an intentional change in PB 12.6 but unfortunately was not included in the documentation.


Below is what I heard back from engineering on CR 777799 that I opened for a different customer experiencing this issue.

When you use a structure or structure array as an external function, in the old version of PowerBuilder, the structure member alignment was one byte.  With Windows API and Visual C++ default option(in PB 12.6), the structure member alignment is 8 bytes. You must add some padding member in your structure definition. For x64 applications, the problem becomes more serious as the length of the pointer is 8 bytes. To work around this engineering changed the  structure member alignment to 8 bytes for PB126 for both x64 and x32 applications.  This is an intentional behavior change.  Customers may need to make some changes for some special cases with their external function call, but they can call Window API more easily and use same code for both x64 and x32 applications.

A fix that enables two workarounds to switch to the pre-PB 12.6 behavior has been implemented as a result of CR 777799.  I do not know when an EBF with this fix will be available to customers as it was just recently implemented.


Pat Steinhardt

Former Member
0 Kudos

Hi Pat;

  That is not a fix its a "kluge" workaround that can not support both. I can see where a PB application is calling older 3rd party DLL's and new ones where the alignment could be a mixed bag.

  The proper fox would be to change the structure painter to tag the entire structure or by structure item (element) if a word boundary alignment is required.

Just my $0.02

Regards ... Chris

Former Member
0 Kudos

Kerthunk!! Another nail in the coffin.

It is inconceivable that any responsible manufacturer or any manager at any level could allow such a major change, and a far reaching one for some customers, and then 'forget' to document it.

As Chris says the solution is nothing but a kludge.

Thanks again, SAP.

Former Member
0 Kudos

Incident reported to SAP: 31101 / 2015.

Still waiting for a solution...

Former Member
0 Kudos

Hi Werner;

  OUCH .. that would be a major issue with many PB applications! I hope that this is a bug with the 12.6 release ... otherwise a major migration shop stopper IMHO.

BTW: I am assuming that you are using PB Classic?

Regards ... Chris

PS: Reminds me of my old Assembler days when we could ask for variables to be aligned on a word boundary. 

Former Member
0 Kudos

Yes, I am using PB Classic.