1. Rudolf Alexander Kerbitz
  2. PowerBuilder
  3. Thursday, 23 January 2020 08:20 AM UTC

Let n_pbni denote a non-visual object exported by a PBNI-Extension and let n_derived denote a class that was inherited from n_pbni. Assume that n_derived's constructor and destructor are implemented and reference global variables that are part of the corresponding application object.

In constrast to pure powerscript hierarchies the statement CREATE n_derived would solely call PBX_CreateNonVisualObject and neglegt the constructor of n_derived.

As mentioned here the implementation of n_derived's base class n_pbni has to assure that the constructor of n_derived is called too. Therefore during the call to PBX_CreateNonVisualObject the pbobject instance passed to it is used retrieve its specific class type and when this differs from the native class type to trigger it's constuctor event. This way n_derived is instantiated correctly when the statement CREATE n_derived is evaluated.

The surprise comes when trying to open the script of n_derived in a painter:

On a side note, everytime a PBNI object is opened with the user object painter an instance of the PBNI-object is created. This also applies for objects inheriting a PBNI-object:

  1. Clicking on n_derived will open the painter.
  2. The painter calls PBX_CreateNonVisualObject for n_pbni with a pbobject instance of type n_derived
  3. n_pbni triggers the constructor of n_derived
  4. the constructor of n_derived fails with an exception since the global variable of the application object was not instantiated.
  5. The painter is closed before it was even showing.

When replacing the base of n_derived with a non-PBNI base class the painter just opens without triggering any constructor/destructor events.

So in order to mimic the same behaviour for PBNI based objects and their descendands triggering the constructor/destructor events needs to be ommitted when PBX_CreateNonVisualObject is called from the IDE's painter.

Is there a way to reliably determine that a PBNI object is being instantiated from within the IDE's painter?

Thanks in advance

Rudolf Alexander Kerbitz

 

Roland Smith Accepted Answer Pending Moderation
  1. Thursday, 23 January 2020 13:43 PM UTC
  2. PowerBuilder
  3. # 1

What version/build of PowerBuilder?

I've created several non-visual PBNI extensions and haven't had any troubles like you describe. I would guess that there is something wrong with the C/C++ code in the extension.

If you can post it somewhere, I would be willing to take a look.

Comment
  1. Rudolf Alexander Kerbitz
  2. Friday, 24 January 2020 10:06 AM UTC
PowerBuilder 2017 R3 Build 1915 as well as PowerBuilder 2019 Build 2170 show the same behaviour. Please take a look at the example project.
  1. Helpful
There are no comments made yet.
Rudolf Alexander Kerbitz Accepted Answer Pending Moderation
  1. Friday, 24 January 2020 10:37 AM UTC
  2. PowerBuilder
  3. # 2

The following image illustrates the objects in the example program contained in BareExample.zip

For convenience I added a compiled version of the DLL, but feel free to compile it yourself from dllmain.cpp. One only requires the PBNI SDK for compiling.

  • n_pbni_v1 does nothing but showing a message-box during construction/destruction
  • n_pbni_v1 shows a message-box during construction/destruction and triggers the constructor of a derived class.
  • n_base does the same as n_pbni_v1 but is plain PowerScript
  • n_derived_v1 to ..v3 also do nothing but showing a message-box during construction/destruction

The application object implements the open-event which does the following:

n_derived_v1 ln_dv1
n_derived_v2 ln_dv2
n_derived_v3 ln_dv3

// n_derived_v1's base class n_pbni_v1
// does not explicitly call the 
// constructor/destructor of its
// descendant. This default behaviour 
// leads to non-initialized objects
// and may cause memory-leaks 
MessageBox("", "CREATE n_derived_v1")
ln_dv1 = CREATE n_derived_v1
MessageBox("", "DESTROY n_derived_v1")
DESTROY ln_dv1

// n_derived_v2's base class n_pbni_v2
// explicitly calls the constructor/
// destructor of its descendant. This
// is the correct behaviour but it 
// can cause trouble when opening the 
// painter. 
MessageBox("", "CREATE n_derived_v2")
ln_dv2 = CREATE n_derived_v2
MessageBox("", "DESTROY n_derived_v2")
DESTROY ln_dv2

// The following shows the expected behaviour:
MessageBox("", "CREATE n_derived_v3")
ln_dv3 = CREATE n_derived_v3
MessageBox("", "DESTROY n_derived_v3")

 

n_derived_v2 and n_derived_v3 show the expected behaviour during execution. As stated above the problem is induced by the painter which creates instances of the native base class when it is opened in the IDE:

  • clicking on n_pbni_v1 to open the coresponding painter would first popup the two messages:
    and
  • clicking on n_pbni_v2 yields the same amount of popups
  • clicking on n_derived_v1 yields four messages due to two instantiations:
    1. n_pbni_v1::constructor
    2. n_pbni_v1::constructor
    3. n_pbni_v1::destructor
    4. n_pbni_v1::destructor
  • clicking on n_derived_v2 yields six messages
    1. n_pbni_v2::constructor
    2. n_derived_v2::constructor
    3. n_pbni_v2::constructor
    4. n_pbni_v2::destructor
    5. n_pbni_v2::destructor
    6. n_derived_v2::destructor
  • clicking on n_derived_v3 yields zero messages, which is the behaviour I would expect for above cases too.

As implied by the messages shown by clicking on n_derived_v2, the IDE painter first creates an instance of the concrete class (i.e. n_derived_v2) and afterwards an instance oft its immediate anchestor class (i.e. n_pbni_v2). Causing lots of Messages popping up.

Attachments (1)
Comment
  1. Roland Smith
  2. Friday, 24 January 2020 16:38 PM UTC
All the painters instantiate the object being opened whether they are standard or PBNI. It has always been that way.
  1. Helpful
  1. Rudolf Alexander Kerbitz
  2. Monday, 27 January 2020 09:01 AM UTC
If this is true for standard objects, then another question arises: How is a painter capable of instantiating a standard object without triggering its constructor and destroy it without triggering its destructor. It cannot be the CREATE, DESTROY statements because these would trigger the constructor or destructor repectively.

There is no evidence that standard objects are instantiated when opened in a painter since construction and destruction is omitted for objects of type n_base and n_derived_v3. There is only proof that PBNI-objects are instantiated.

In order to implement a workaround I still would like to know if there is a way to reliably determine that a PBNI object is being instantiated from within the IDE's painter?
  1. Helpful
There are no comments made yet.
Chris Heale Accepted Answer Pending Moderation
  1. Wednesday, 30 September 2020 21:39 PM UTC
  2. PowerBuilder
  3. # 3

Hello!

Apologies for being off-topic, but we're experiencing something similar to your support case https://www.appeon.com/standardsupport/search/view?id=3736 - our customers are crashing frequently and we'd love to understand how you approached investigating the issues you reported.

If you could spare some time to share your insight, we'd be very grateful... please contact me at cheale.AT.brighthealth.ca

Many thanks!

Chris Heale 

Comment
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.