Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 1999-06

Problem found

13 messages · 7 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ove Kaaven
to Peter Vreman: the problem with signal and methods is that C doesn't know that it need to load the…
Peter Vreman wrote 5 lines
> Thanks for the idea. I was hoping to find a "Delphi-like" way of > handling it. By doing that I would need to set Self = the gtk object > data and that (I think) would start to cause some trouble when I wanted > to remove the code from the units and place them into seperate units for > GTK.....

...

the problem with signal and methods is that C doesn't know that it need to load the object pointer into ESI before calling to method, so it's not possible directly. Maybe with a wrapper it could be possible

Well, Delphi has the same problem under Windows, since window procedures isn't called with a self pointer (only the window handle). Frameworks (like VCL) solves that by using thunks (wrappers); often, these can be a code fragment allocated on the heap that is written to pass an extra argument along, or it can be a normal routine that looks the window handle/widget pointer in some table and finds the associated object, calling the proper method in it.

Reply by email

Michael Van Canneyt
to Shane Miller: Could someone please pull the source from CVS and take a look at this problem and see if…
Shane Miller wrote 9 lines
Could someone please pull the source from CVS and take a look at this problem and see if you can find a way to make this work? I'm having trouble with it. 2 things you need to do after pulling the latest version: Uncomment (if it's commented out yet) the AssignOwnEvents method in the TMemo.Create procedure in stdcontrols.pp and in editor.pp go to the Memo1Change procedure and tell it to writeln(Caption) or something so you can see that when you try to access anything throuigh "SELF" that it throws an exception.

The solution is documented in the new manuals. We now support the following construct:

Procedure TMyObject.MyCallback (Var Var1: Type1;Self : TMyObject); message 'changed'; cdecl;
begin
  // This will load self from the second parameter.
end;

So you declare your callback function with the correct number of arguments, (so it matches the gtk_signal_func) and then you do a

gtk_signal_connect(gtk_object(fcomponent),'changed',gtk_signal_func(MyCallback),Self)

Self will be passed through the 'self' argument.

This was implemented especially for GTK and QT; see the docs for more info.

If it isn't clear, just ask.

Michael.

Reply by email

Shane Miller
the problem with signal and methods is that C doesn't know that it need to load the object pointer into ESI before calling to method, so it's not possible directly. Maybe with a wrapper it could be possible

The problem with wrapping the signal connect is that I think it'll still lose the SELF value because it's a callback..... If I call a method of TCustomMemo like proceure TCustomMemo.Test(Number : Integer); what it's really doing is sending an integer AND the value of SELF right? If that's the case, can I call that procedure and actually SEND it the value of SELF by calling it like this: Test(4,self) ? If I could do that then I could write a wrapper, otherwise I'm not sure how to do it..

Shane

Reply by email

Shane Miller

Thanks for the idea. I was hoping to find a "Delphi-like" way of handling it. By doing that I would need to set Self = the gtk object data and that (I think) would start to cause some trouble when I wanted to remove the code from the units and place them into seperate units for GTK.....

Here's another thought.....I was in the shower this morning, like I often am, when I thought of this. Perhaps if I used methods as the procedure to assign the signal to instead of generic procedures then perhaps it would retain it's information. For example:

I tried to move the gtkOnChange and gtkMoveToRow procedures into the TCustomMemo class. Once I did that I added TCUSTOMMEMO. in front of the names of the proceures and tried to compile. I got this error again:

ERROR: Method (variable) and Procedure (variable) are not compatable.

Is there anyway to assign a signal to a METHOD instead of an ordinary procedure?

Shane

>> 06/28 10:58 PM >>>

Shane Miller on 29/06/99 15:14:25
I have set up TMemo to use the "changed" signal and when GTK fires that signal I do :

      If assigned FChanged then FChanged(Self);

Obviously when the callback is used, the connection to self is lost and therefore it's children no longer retain their values.

You can associate an arbitrary piece of data with a GTK widget. In programming with GTK in the past, I have used something like

gtk_object_set_data(widget,"Self",self)

In the signal handler you can just do

sig_handler(Widget widget....)

...

    self = gtk_object_get_data(GTK_OBJECT(widget),"Self");

This works well in C, but I haven't had any reason to do it under fpc...

OR we could port gtk-- to pascal :-)

J.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Jan Schmidt
Information Technologist - Business Services
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Advitech Pty Limited - Industry's Technology Resource Centre 1 Elizabeth Street, Tighes Hill NSW, Newcastle, Australia PO Box 207, Mayfield 2304 NSW, Australia
Phone +61 2 49616544
Fax +61 2 49693530
http://www.advitech.com.au
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

_________________________________________________________________ To unsubscribe: mail with
"unsubscribe" as the Subject
archives at http://www.miraclec.com/list_archives/lazarus

Reply by email

Shane Miller

I changed my statement in stdcontrols from
onchangeint := gtk_signal_connect(gtk_object(fcomponent),'changed',gtk_signal_func(gtkonChange),Self) to
gtk_signal_connect(gtk_object(fcomponent),'changed',gtk_signal_func(TCustomMemo.gtkonChange),Self)

and when I try to compile I get

Panic: Internal compiler error, exiting.
stdcontrols.pp (398,115) Fatal: Internal Error 9999

thoughts?

Shane

>> "Shane Miller" 06/29 10:43 AM >>>

Thanks for the idea. I was hoping to find a "Delphi-like" way of handling it. By doing that I would need to set Self = the gtk object data and that (I think) would start to cause some trouble when I wanted to remove the code from the units and place them into seperate units for GTK.....

Here's another thought.....I was in the shower this morning, like I often am, when I thought of this. Perhaps if I used methods as the procedure to assign the signal to instead of generic procedures then perhaps it would retain it's information. For example:

I tried to move the gtkOnChange and gtkMoveToRow procedures into the TCustomMemo class. Once I did that I added TCUSTOMMEMO. in front of the names of the proceures and tried to compile. I got this error again:

ERROR: Method (variable) and Procedure (variable) are not compatable.

Is there anyway to assign a signal to a METHOD instead of an ordinary procedure?

Shane

>> 06/28 10:58 PM >>>

Shane Miller on 29/06/99 15:14:25
I have set up TMemo to use the "changed" signal and when GTK fires that signal I do :

      If assigned FChanged then FChanged(Self);

Obviously when the callback is used, the connection to self is lost and therefore it's children no longer retain their values.

You can associate an arbitrary piece of data with a GTK widget. In programming with GTK in the past, I have used something like

gtk_object_set_data(widget,"Self",self)

In the signal handler you can just do

sig_handler(Widget widget....)

...

    self = gtk_object_get_data(GTK_OBJECT(widget),"Self");

This works well in C, but I haven't had any reason to do it under fpc...

OR we could port gtk-- to pascal :-)

J.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Jan Schmidt
Information Technologist - Business Services
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Advitech Pty Limited - Industry's Technology Resource Centre 1 Elizabeth Street, Tighes Hill NSW, Newcastle, Australia PO Box 207, Mayfield 2304 NSW, Australia
Phone +61 2 49616544
Fax +61 2 49693530
http://www.advitech.com.au
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

_________________________________________________________________ To unsubscribe: mail with
"unsubscribe" as the Subject
archives at http://www.miraclec.com/list_archives/lazarus

_________________________________________________________________ To unsubscribe: mail with
"unsubscribe" as the Subject
archives at http://www.miraclec.com/list_archives/lazarus

Reply by email

T Jan Schmidt
to Shane Miller: I updated CVS so you'll now be able to see the problem in action without changing…

In C++, I got around the problem of having no self (this) pointer by making a global function as the callback, and having a self pointer as part of the widget data (as in my previous email). I was looking for a quick and dirty fix, so I used public methods on the class(object) and simply typecast the widget data "self" pointer to the type I wanted, then called the public method on that object.

A better solution (in C++) would have been something like:

class X {
  friend void callback(...);
private:
   void Handler();
};
void callback(...)
{
  X *obj = ( X* (gtk_object_get_data(GTK_OBJECT(Widget),"self")));
  obj)->Handler();
};

This relies on the "friend" C++ construct. I don't know if there is an equivalent for Delphi - a modifier that says a global function is allowed to call private member functions on the object. If there isn't, I don't see a solution that doesn't involve making the object methods public.

AAnyone?

Jan.

Reply by email

Shane Miller

Found a problem:
I have set up TMemo to use the "changed" signal and when GTK fires that signal I do :
If assigned FChanged then FChanged(Self);

In Editor.pp I have a function called Memo1Change(Sender : TObject);
It gets called when the TMemo class calls FChanged(Self);

The problem is that when your in TEditor.Memo1Change, it no longer has any reference to TEditor's properties (like it's caption, left and top values, etc) and if you try to access Memo1 which is a child of TEditor, an exception is thrown.
Obviously when the callback is used, the connection to self is lost and therefore it's children no longer retain their values.

Any thoughts on a solution?
Feel free to look at the code.
Go into stdcontrols.pp and look at TMemo's create. It has a function commented out called AssignOwnEvents. remove the comments and save the file.
Now go into the editor.pp file and go to the procedure Memo1Change and add some code like

Writeln('The caption of the editor is '+Caption);

Compile and run. When you OPEN a file, click on the memo. Then press a key and the onchange event should fire. You'll notice the exception occurs there.......please help!

Shane

Reply by email

Unknown author

Shane Miller on 29/06/99 15:14:25
I have set up TMemo to use the "changed" signal and when GTK fires that signal I do :

      If assigned FChanged then FChanged(Self);

Obviously when the callback is used, the connection to self is lost and therefore it's children no longer retain their values.

You can associate an arbitrary piece of data with a GTK widget. In programming with GTK in the past, I have used something like

gtk_object_set_data(widget,"Self",self)

In the signal handler you can just do

sig_handler(Widget widget....)

...

    self = gtk_object_get_data(GTK_OBJECT(widget),"Self");

This works well in C, but I haven't had any reason to do it under fpc...

OR we could port gtk-- to pascal :-)

J.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Jan Schmidt
Information Technologist - Business Services
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Advitech Pty Limited - Industry's Technology Resource Centre 1 Elizabeth Street, Tighes Hill NSW, Newcastle, Australia PO Box 207, Mayfield 2304 NSW, Australia
Phone +61 2 49616544
Fax +61 2 49693530
http://www.advitech.com.au
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Reply by email

Ove Kaaven
to Shane Miller: The problem with wrapping the signal connect is that I think it'll still lose the SELF…
Shane Miller wrote 10 lines
>the problem with signal and methods is that C doesn't know that it need to >load the object pointer into ESI before calling to method, so it's not >possible directly. Maybe with a wrapper it could be possible The problem with wrapping the signal connect is that I think it'll still lose the SELF value because it's a callback..... If I call a method of TCustomMemo like proceure TCustomMemo.Test(Number : Integer); what it's really doing is sending an integer AND the value of SELF right?

This is correct. The Self is sent implicitly though.

If that's the case, can I call that procedure and actually SEND it the value of SELF by calling it like this: Test(4,self) ? If I could do that then I could write a wrapper, otherwise I'm not sure how to do it..

You could probably do TCustomMemo(selfpointer).Test(4)

Reply by email

Shane Miller

Could someone please pull the source from CVS and take a look at this problem and see if you can find a way to make this work? I'm having trouble with it. 2 things you need to do after pulling the latest version:

Uncomment (if it's commented out yet) the AssignOwnEvents method in the TMemo.Create procedure in stdcontrols.pp and in editor.pp go to the Memo1Change procedure and tell it to writeln(Caption) or something so you can see that when you try to access anything throuigh "SELF" that it throws an exception.

Any thoughts or code fixes would be GREATLY appreciated.

Thanks
Shane

Reply by email

Shane Miller

I updated CVS so you'll now be able to see the problem in action without changing anything. I created a variable called TRAGS in TEditor and I set it in Colorize. When you open a file, it gets Colorized (tags is set to 27) and then when you click on the memo and press a key, the change event gets fired. In Memo1Change I try to display tags and it crashes...

WHY???? What happened to self??????

Shane

Reply by email

Peter Vreman
to Shane Miller: Thanks for the idea. I was hoping to find a "Delphi-like" way of handling it. By doing…
Show quoted text 19 lines
Thanks for the idea. I was hoping to find a "Delphi-like" way of handling it. By doing that I would need to set Self = the gtk object data and that (I think) would start to cause some trouble when I wanted to remove the code from the units and place them into seperate units for GTK..... Here's another thought.....I was in the shower this morning, like I often am, when I thought of this. Perhaps if I used methods as the procedure to assign the signal to instead of generic procedures then perhaps it would retain it's information. For example: I tried to move the gtkOnChange and gtkMoveToRow procedures into the TCustomMemo class. Once I did that I added TCUSTOMMEMO. in front of the names of the proceures and tried to compile. I got this error again: ERROR: Method (variable) and Procedure (variable) are not compatable. Is there anyway to assign a signal to a METHOD instead of an ordinary procedure?

the problem with signal and methods is that C doesn't know that it need to load the object pointer into ESI before calling to method, so it's not possible directly. Maybe with a wrapper it could be possible

Peter

Reply by email