paragui-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [paragui-users] Bugs in 1.0.3


From: Alexander Pipelka
Subject: Re: [paragui-users] Bugs in 1.0.3
Date: 19 Jun 2003 13:18:27 +0200

Hi Mark!

Thanks for your help!

ad 1,2:
I fixed the PG_Widget userdata stuff. Definitely a bug :)

ad 3:
For the DEFINE thing i currently can't figure out what 
PARAGUI_DYNAMIC_EXPORTS should do. SDL defines the DECLSPEC macro to
handle symbol export. Your code would prevent dynamic export of symbols
if PARAGUI_DYNAMIC_EXPORTS is *not* defined. Hmm,...

ad 4:
I can see the point. I can see that your explanation should be right.
But after this I *don't* know why the current implementation has been
reported to work on Linux (GCC Versions: 2.91, 2.95, 3.0, 3.2), Windows
(VC++, DevC++ gcc 2.95, gcc 3.2, Code Warrior 7), BeOS, MacOS (Code
Warrior 7), MacOS X, FreeBSD.

I would be very glad if this could be fixed, but there's currently no
motivation for me because it just works for the platforms I'm using (I
know this attitude i technically not ok, but who cares).

Maybe an easy fix (but possibly breaking binary compatibility) would be
to subclass PG_MessageObject from PG_EventObject. This way all offsets
should be correct.

Alex

Am Sam, 2003-06-14 um 15.03 schrieb Mark Junker:
> Hi,
> 
> I currently received ParaGUI v1.0.3 and its a quite good work. Anyway, while  
> porting the sources to Borland C++ Builder 5, I've found several bugs in it:
> 
> 1. Wrong new instruction
> File: pgwidget.cpp
> Fn. : PG_Widget::SetUserData(void *userdata, int size)
> Line from: my_internaldata->userdata = new char(size);
>        to: my_internaldata->userdata = new char[size];
> 
> 2. Usage of free() instead of delete[]
> File: pgwidget.cpp
> Fn. : Destructor
> Line from: free(my_internaldata->userdata);
>        to: delete[] my_internaldata->userdata;
> 
> 3. Missing DEFINEs
> You don't use the DEFINE PARAGUI_DYNAMIC_EXPORTS.
> However, you should include the following lines into paraconfig_win32.h or
> similar:
> ------------------------------------------------------------------
> #ifdef DECLSPEC
> #undef DECLSPEC
> #endif
> 
> #ifdef PARAGUI_DYNAMIC_EXPORTS
> #define DECLSPEC __declspec(dllexport)
> #else
> #define DECLSPEC
> #endif
> ------------------------------------------------------------------
> 
> 4. Non-Working event mechanism
> When adding a function to the list of event handler using the following line
> (or something similar):
> ------------------------------------------------------------------
> m_pEditBox->SetEventObject(MSG_EDITEND, this, (MSG_CALLBACK_OBJ)
> &PG_SpinnerBox::handle_editend);
> ------------------------------------------------------------------
> The variable "this" will be converted to point to the beginning of the
> "PG_EventObject" portion of the current class. Depending on the
> compiler, it will be inserted at the beginning or appended to the end
> of the class.
> In other words: the conversion of "this" depends on the order of the
> parent classes.
> 
> Example:
> ------------------------------------------------------------------
> #include <stdio.h>
> class TTestBaseA {
>         int a;
> };
> class TTestBaseB {
>         int b;
> };
> void test_a(TTestBaseA *pTest) {
>         printf("Base of TTestBaseA* = %p\n", pTest);
> }
> void test_b(TTestBaseB *pTest) {
>         printf("Base of TTestBaseB* = %p\n", pTest);
> }
> class TTest : public TTestBaseA, public TTestBaseB {
>         int c;
>         void test(void) {
>                 test_a(this);
>                 test_b(this);
>         }
> };
> int main(int argc, char **argv) {
>         TTest t;
>         t.test();
>         return 0;
> }
> ------------------------------------------------------------------
> 
> As you can see, the pointers of TTestBaseA* and TTestBaseB* are different.
> The address of TTestBaseA* might be lower than TTestBaseB*, but you must not
> rely on it.
> 
> This behaviour is causing the crash, when the following line
> (pgmessageobject.cpp) will be executed:
> 
> rc = ((cbdata->calledobj)->*(cbdata->obj_cbfunc))(id, (PG_Widget*)this, data,
> cbdata->data);
> 
> The compiler thinks that obj_cbfunc points to a member function of
> PG_EventObject and therefore the address of "this" in the event handler is
> probably wrong (depending on the compiler/platform) because it doesn't point
> to the base of the - for example - PG_SpinnerBox object. It contains the
> address of the PG_EventObject inside this object.
> 
> I ran into this error when I used the Borland C++ Builder 5.
> 
> Please re-think the event mechanism because this is seriously a bug that has
> to be fixed.
> 
> What about using libsigc++ or a "generic" event handler like:
> virtual bool ProcessMessage(TEvent *pEvent);
> 
> where the ProcessMessage method tests for the event type and - if it is known
> - casts the pEvent pointer to TEventMouse or TEventKeyboard objects which are
> derived from TEvent and calls another virtual function that tries to handle
> this special event.
> 
> #define eET_Paint 1
> #define eET_MouseClick 2
> #define eET_MouseMove 3
> 
> struct TEvent {
>   int Type;
> };
> 
> struct TEventMouse {
>   bool Left;
>   bool Right;
>   bool Middle;
>   int  x, y;
> };
> 
> bool PG_MessageObject::ProcessMessage(TEvent *pEvent) {
>   /* do nothing */
>   return false;
> }
> 
> bool PG_Widget::ProcessMouseClick(TEventMouse *pEvent) {
>   return false;
> }
> 
> bool PG_Widget::ProcessMouseMove(TEventMouse *pEvent) {
>   return false;
> }
> 
> bool PG_Widget::ProcessMouseMessage(TEventMouse *pEvent) {
>   if (pEvent->Type==eET_MouseClick) {
>     return ProcessMouseClick(pEvent);
>   } else if (pEvent->Type==eET_MouseMove) {
>     return ProcessMouseMove(pEvent);
>   }
> }
> 
> bool PG_Widget::ProcessMessage(TEvent *pEvent) {
>   bool fResult = false;
>   switch (pEvent->Type) {
>   case eET_MouseClick:
>   case eET_MouseMove:
>     fResult = ProcessMouseMessage((TEventMouse*) pEvent);
>   }
>   if (!fResult) {
>     fResult = PG_MessageObject::ProcessMessage(pEvent);
>   }
>   return fResult;
> }
> 
> .
> .
> .
> .
> 
> and so on ...
> 
> I took a look at libsigc++ v1.2.5 - they use the same C++ language feature -
> and it only works because they
> 
> 1. store both object pointers (of SigC::Object and the user-defined class
> derived from SigC::Object)
> 2. pass both object pointers to a function (which stores them) after
> converting them to (void*) to get rid of implicit type casts
> 
> Maybe it's possible to make some small changes to get it up and running
> without seg faults ... but this mechanism doesn't seem to be very easy to
> maintain (just take a look at the configuration stuff of libsigc++).
> 
> Regards,
> Mark Junker
> 
> 
> _______________________________________________
> paragui-users mailing list
> address@hidden
> http://mail.nongnu.org/mailman/listinfo/paragui-users





reply via email to

[Prev in Thread] Current Thread [Next in Thread]