2017-02-10 2 views
1

J'essaie d'utiliser des procédures dans un type de données structuré comme fonctions de rappel pour un programme utilisant GTK + 3 comme sa boîte à outils dans FreePascal. (Dans l'exemple ci-dessous, j'utilise des enregistrements avancés, mais je considérerais certainement les classes ou les objets si cela fonctionne mieux/pas du tout avec eux.Utilisation de la procédure dans le type de données structuré comme rappel pour la bibliothèque C (GTK + 3)

Le problème qui se produit est que lorsque la procédure de rappel est appelée, il ne peut pas accéder à autre chose dans son propre enregistrement. Il semble "oublier" d'où il vient. Par exemple, dans l'exemple ci-dessous, j'ai l'entier myRecord.myInt, que je peux définir et récupérer facilement en appelant la procédure myRecord.testProcedure. Toutefois, lorsque testProcedure est utilisé comme un rappel C (lorsque je clique sur le bouton), je recevrai un certain nombre (par exemple 30976), mais pas 7.

{$MODESWITCH ADVANCEDRECORDS} 
uses gobject2, gtk3, math; 

type 
    myRecord=record 
    public 
     myInt: Integer; 
     procedure testProcedure; cdecl; 
    end; 

    procedure myRecord.testProcedure; cdecl; 
    begin 
    WriteLn(myInt); 
    end; 

var 
    recordInstance: myRecord; 
    button, win: PGtkWidget; 
begin 
    SetExceptionMask([exDenormalized, exInvalidOp, exOverflow, 
    exPrecision, exUnderflow, exZeroDivide]); {this is needed for GTK not to crash} 

    gtk_init(@argc, @argv); 

    win:=gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    recordInstance.myInt:=7; 

    button:=gtk_button_new; 

    {The following does not work. The procedure will run when the button is 
    clicked; it will print some number, but not the content of recordInstance.myInt} 
    g_signal_connect_data(button, 'clicked', 
    TGCallback(@recordInstance.testProcedure), nil, nil, 0); 

    {add button to window} 
    gtk_container_add(PGtkContainer(win), button); 

    gtk_widget_show_all(win); 

    {Test call to recordInstance.testProcedure to see that it outputs 
    '7' correctly} 
    recordInstance.testProcedure; 

    gtk_main; 
end. 

Lorsque je tente d'utiliser des classes ou des objets au lieu d'une avancée Record, je reçois des messages d'erreur du type

"<procedure variable type of procedure of object;CDecl>" to "<procedure variable type of procedure;CDecl>" 

Quels sont les moyens d'utiliser un type de données structuré avec une procédure à utiliser comme un rappel de C comme dans l'exemple ci-dessus (le cas échéant)?

+0

Je suppose que C n'a aucun moyen d'utiliser une méthode comme un rappel. L'appel de méthode doit être converti en un appel de procédure ordinaire. Voir [Comment passer une méthode en rappel d'un appel d'API Windows?] (Http://stackoverflow.com/q/2787887/576719). –

Répondre

1

Les méthodes statiques de classe sont compatibles avec les procédures. Mais ils ont aussi le désavantage de ne pas avoir de référence aux données de l'objet.

{$mode delphi} 

type 
    myRecord=record 
    public 
     myInt: Integer; 
     class procedure testProcedure; cdecl;static; 
    end; 

    tproctype = procedure; cdecl; 

class procedure myrecord.testProcedure; cdecl;static; 
begin 
end; 

var x : tproctype; 
    y : myrecord; 
begin 
x:=y.testprocedure; 
end. 

compiles, mais l'usage est stérile, car si elle correspond à C plaine, il ne dispose pas (implicites) propriétés OO.