Sign in Join

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

Mailing lists / fpc-pascal / 2002-11

Re: About callbacks method of a class

2 messages · 1 person ·

Reply by email Subscribe to this list Your subscription

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

Unknown author

Noting that I know nothing about the way GTK works with Object Pascal from a FPC perspective...

Your problem is the callback itself. The procedure has the right signature, but it is attached to the Class, and so is going to cause you untold woes.

You want (by the look of it) the following:

type
  procedure (widget:PGtkWidget; data:Object); cdecl;

but what you actually have is:

type
  procedure (widget:PGtkWidget; data:Object) of object; cdecl;

I once found a convoluted way of converting the VMT pointer to a Function pointer, but it was unreliable.

A nasty, but fairly simple, solution would be to write a single callback and dispatch it to the correct control. If anyone knows a better way, please feel free to chip in ;-) (NB. I have *not* compiled the code below, indeed I doubt it will compile without modification. It is meant to be a guide of sorts.)

e.g.

  TButton = class(Tobject)
  private
    FButton:PGtkWidget;
  public
    constructor Create; virtual;
    destructor  Destroy; override;
    property OnClick: TNotifyEvent; //this is the usual Delphi way
  end;//TButton
  var
    ButtonList: TStringList; //just for look up simplicity
  procedure InitList; //this has to be called before using controls
  begin
    ButtonList := TStringList.Create;
  end;
  function RegButton(name: string; Button: TButton): integer;
  begin
    Buttonlist.AdObject(name, Button);
  end;
  function FindButton(name: string): TButton;
  var
    idx: integer;
  begin
    idx := Buttonlist.Indexof(name);
    if idx > -1 then begin
      Result := TButton(ButtonList.Objects[i]);
    end
    else
      Result := nil;
  end;
  function FindPointer(widget:PGtkWidget): TButton;
  var
    aname: string;
  begin
    //get the widgets name..
    aname := ???? //must be a way of doing this...
                  //I have no knowledge of GTK though
    Result := FindButton(aname);
  end;
  procedure globalCallback_OnClick(widget:PGtkWidget; data:Object); cdecl;
  var
    abutton: TButton;
  begin
    abutton := FindPointer(widgit);
    if assigned(abutton) then
       abutton.OnCLick(nil); //you'll have to decide who the sender is I guess
  end;
  constructor TButton.Create;
  begin
    inherited Create;
    FButton:=gtk_button_new_with_label('Click Me!');
    gtk_widget_show(FButton);
    g_signal_connect(G_OBJECT(FButton),'clicked',
      TGCALLBACK(@globalCallback_OnClick),self);
    ...
  end;//TButton.Create
Show quoted text 12 lines
Hello, everybody I am using gtk2forpascal. I want to program as follows: >>>>> TButton = class(Tobject) private FButton:PGtkWidget; public constructor Create; destructor Destroy; procedure Callback_OnClick(widget:PGtkWidget; data:Object); cdecl; end;//TButton

---------------------------------------------
This message was sent using Mistral WebMail.
http://www.mistral.co.uk/

Unknown author

Now that's much nicer :-)

Show quoted text 22 lines
Right, procedures and methods (= procedures of object) are not compatible. You have to write your own mapper. For example: type TButton = class procedure OnClickCallback(Widget: PGtkWidget); end; procedure TButton.OnClickCallback(Widget: PGtkWidget); begin end; procedure Callback_TButton_OnClick(widget:PGtkWidget; data:Object); cdecl; begin TButton(Data).OnClickCallback(Widget); end; begin g_signal_connect(G_OBJECT(FButton),'clicked', TGCALLBACK(@Callback_TButton_OnClick),FButton); end.

---------------------------------------------
This message was sent using Mistral WebMail.
http://www.mistral.co.uk/