Discussion:
Les Callback en Ada
(trop ancien pour répondre)
Danielle Mandi Mayagha
2021-09-16 02:29:57 UTC
Permalink
Salut Salut Je viens avec un tout petit (un gros enfaite) problème qui me sauf un peu le cerveau. bon voila! j'essaie de faire un Callback avec un Bouton mais le souci c'est que ce bon vieux Gnat me dit ceci ( pour info je suis carrément nul en anglais😊😛) :
Instantiation error at gtk-handlers.ads : 1039
Subprogram must not be deeper than access type.

plus loin Gnat dit encore ceci :
No candidate interpretations match the actuals:
expected type "handler" defined at gtk-marshaller.ads :395, instance at gtk-handlers :918 , instance at line 10.
Found type access to procedure "Stop_Program" defined at line 38.
=> in call to "to_marshaller" at gtk-handlers.ads :959, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :954, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :949, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :944, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :939, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :935, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :931, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :927, ainstance at line 10
=> in call to "to_marshaller" at gtk-handlers.ads :923, ainstance at line 10

voici mon code :

WITH Gtk.Main; USE Gtk.Main;
WITH Gtk.Widget; USE Gtk.Widget;
WITH Gtk.Window; USE Gtk.Window;
WITH Gtk.Enums; USE Gtk.Enums;
WITH Gtk.Button; USE Gtk.Button;
WITH Gtk.Handlers;

Procedure Test is

Package P_Callback is new Gtk.Handlers.Callback (Gtk_Widget_Record);
USE P_Callback;

Procedure Stop_Program ( Emetteur : Gtk_Widget_Record'Class ) is
Pragma Unreferenced (Emetteur);
begin
Main_Quit;

end Stop_Program;

Win : Gtk_Window;
Bouton : Gtk_Button;

begin
Init;

Gtk_New (Win);
Win.Set_Default_Size (600,400);

Gtk_New (Bouton,"Le Bouton");


Win.Add (Bouton);

P_Callback.Connect (Bouton,"Clicked", To_marshaller (Stop_Program'Access));

Win.Show_All;
Main;
end Test;

Voila pour vous dire vrai je ne vois aucun probleme donc si quelqu'un pouvait m'expliquer ce qui cloche j'en serai vraiment ravi.

pour info je suis sur Windows10 et j'utilise la version Gnat 2020.
J-P. Rosen
2021-09-16 08:48:40 UTC
Permalink
Post by Danielle Mandi Mayagha
Instantiation error at gtk-handlers.ads : 1039
Subprogram must not be deeper than access type.
[...]
Post by Danielle Mandi Mayagha
WITH Gtk.Main; USE Gtk.Main;
WITH Gtk.Widget; USE Gtk.Widget;
WITH Gtk.Window; USE Gtk.Window;
WITH Gtk.Enums; USE Gtk.Enums;
WITH Gtk.Button; USE Gtk.Button;
WITH Gtk.Handlers;
Procedure Test is
Package P_Callback is new Gtk.Handlers.Callback (Gtk_Widget_Record);
USE P_Callback;
Procedure Stop_Program ( Emetteur : Gtk_Widget_Record'Class ) is
Pragma Unreferenced (Emetteur);
begin
Main_Quit;
end Stop_Program;
Ici, Stop_Program est un sous-programme interne à la procédure Test
Post by Danielle Mandi Mayagha
Win : Gtk_Window;
Bouton : Gtk_Button;
begin
Init;
Gtk_New (Win);
Win.Set_Default_Size (600,400);
Gtk_New (Bouton,"Le Bouton");
Win.Add (Bouton);
P_Callback.Connect (Bouton,"Clicked", To_marshaller (Stop_Program'Access));
Le type attendu par To_Marshaller est un pointeur global. On ne peut lui
passer un sous-programme local, car il y aurait un risque de pouvoir
accéder au sous-programme après être sorti de sa portée.

Le plus simple: sors Stop_Program de Test en le mettant dans un fichier
séparé. (bien sûr, pour pouvoir y accéder, Test devra faire un "with
Stop_Program;")
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52
https://www.adalog.fr
Danielle Mandi Mayagha
2021-09-16 23:20:49 UTC
Permalink
Post by J-P. Rosen
Post by Danielle Mandi Mayagha
Instantiation error at gtk-handlers.ads : 1039
Subprogram must not be deeper than access type.
[...]
Post by Danielle Mandi Mayagha
WITH Gtk.Main; USE Gtk.Main;
WITH Gtk.Widget; USE Gtk.Widget;
WITH Gtk.Window; USE Gtk.Window;
WITH Gtk.Enums; USE Gtk.Enums;
WITH Gtk.Button; USE Gtk.Button;
WITH Gtk.Handlers;
Procedure Test is
Package P_Callback is new Gtk.Handlers.Callback (Gtk_Widget_Record);
USE P_Callback;
Procedure Stop_Program ( Emetteur : Gtk_Widget_Record'Class ) is
Pragma Unreferenced (Emetteur);
begin
Main_Quit;
end Stop_Program;
Ici, Stop_Program est un sous-programme interne à la procédure Test
Post by Danielle Mandi Mayagha
Win : Gtk_Window;
Bouton : Gtk_Button;
begin
Init;
Gtk_New (Win);
Win.Set_Default_Size (600,400);
Gtk_New (Bouton,"Le Bouton");
Win.Add (Bouton);
P_Callback.Connect (Bouton,"Clicked", To_marshaller (Stop_Program'Access));
Le type attendu par To_Marshaller est un pointeur global. On ne peut lui
passer un sous-programme local, car il y aurait un risque de pouvoir
accéder au sous-programme après être sorti de sa portée.
Le plus simple: sors Stop_Program de Test en le mettant dans un fichier
séparé. (bien sûr, pour pouvoir y accéder, Test devra faire un "with
Stop_Program;")
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52
https://www.adalog.fr
merci beaucoup ça fonctionne tres bien maintenant
Danielle Mandi Mayagha
2021-09-20 00:51:16 UTC
Permalink
Post by Danielle Mandi Mayagha
Post by J-P. Rosen
Post by Danielle Mandi Mayagha
Instantiation error at gtk-handlers.ads : 1039
Subprogram must not be deeper than access type.
[...]
Post by Danielle Mandi Mayagha
WITH Gtk.Main; USE Gtk.Main;
WITH Gtk.Widget; USE Gtk.Widget;
WITH Gtk.Window; USE Gtk.Window;
WITH Gtk.Enums; USE Gtk.Enums;
WITH Gtk.Button; USE Gtk.Button;
WITH Gtk.Handlers;
Procedure Test is
Package P_Callback is new Gtk.Handlers.Callback (Gtk_Widget_Record);
USE P_Callback;
Procedure Stop_Program ( Emetteur : Gtk_Widget_Record'Class ) is
Pragma Unreferenced (Emetteur);
begin
Main_Quit;
end Stop_Program;
Ici, Stop_Program est un sous-programme interne à la procédure Test
Post by Danielle Mandi Mayagha
Win : Gtk_Window;
Bouton : Gtk_Button;
begin
Init;
Gtk_New (Win);
Win.Set_Default_Size (600,400);
Gtk_New (Bouton,"Le Bouton");
Win.Add (Bouton);
P_Callback.Connect (Bouton,"Clicked", To_marshaller (Stop_Program'Access));
Le type attendu par To_Marshaller est un pointeur global. On ne peut lui
passer un sous-programme local, car il y aurait un risque de pouvoir
accéder au sous-programme après être sorti de sa portée.
Le plus simple: sors Stop_Program de Test en le mettant dans un fichier
séparé. (bien sûr, pour pouvoir y accéder, Test devra faire un "with
Stop_Program;")
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52
https://www.adalog.fr
merci beaucoup ça fonctionne tres bien maintenant
Salut désolé encore si je dérange mais j'ai un second souci que j'arrive pas à résoudre( voila je donne un exemple du code apres j'explique le probleme)

ficfier.ads

with Gtk.File_chooser_dialog; use gtk.file_file_chooser_dialog;
with gtk.widget; use gtk.widget;
with gtk.handlers;

package P_fichier is

type T_Type is record

F : Gtk_file_chooser_dialog;

end record;

package Callback is new gtk.handlers.user_callback (gtk_widget_record, P_fichier.T_Type);

use Callback;

Procedure Stop_Program ( emetteur : access gtk_widget_record;
object : out P_fichier.T_Type );

end P_fichier;

fichier.adb

package body P_fichier is

Procedure Stop_Program is (emetteur : access gtk_widget_record;
object : out P_fichier.T_type ) is
pragma Unreferenced (emetteur);

begin

gtk_new (Object.F, "ajout du fichier", action_Save, null);

end Stop_Program;
end P_fichier;

main_program.adb

with gtk.main; use gtk.main;
with gtk.window; use gtk.window;
with gtk.button; use gtk.button;
with P_fichier; use P_fichier;

Procedure main_Program is

win : gtk_window;
bouton : gtk_button;

begin
init;

gtk_new (win);
win.set_default_size (600,400);

gtk_new (bouton,"ouvrir le fichier");

declare

Object : T_Type;

begin

P_fichier.callback.connect (bouton,s signal_clicked, callback.to_marshaller (stop_program'
access, Object, false );

end ;

win.Add (bouton);
win.show_all;
main;
end main_program;

voila le probleme est que le programme affiche le meme message d'erreur que precedent pourtant j'ai bien mis Stop_Program dans un fichier separe. mais je ne comprend pas j'ai essayé avec Object_connect mais c'est toujours pareil.
DrPi
2021-09-20 17:07:02 UTC
Permalink
Bonjour,

Le 20/09/2021 à 02:51, Danielle Mandi Mayagha a écrit :
...
Post by Danielle Mandi Mayagha
Salut désolé encore si je dérange mais j'ai un second souci que j'arrive pas à résoudre( voila je donne un exemple du code apres j'explique le probleme)
ficfier.ads
with Gtk.File_chooser_dialog; use gtk.file_file_chooser_dialog;
with gtk.widget; use gtk.widget;
with gtk.handlers;
package P_fichier is
type T_Type is record
F : Gtk_file_chooser_dialog;
end record;
package Callback is new gtk.handlers.user_callback (gtk_widget_record, P_fichier.T_Type);
use Callback;
Procedure Stop_Program ( emetteur : access gtk_widget_record;
object : out P_fichier.T_Type );
end P_fichier;
fichier.adb
package body P_fichier is
Procedure Stop_Program is (emetteur : access gtk_widget_record;
object : out P_fichier.T_type ) is
pragma Unreferenced (emetteur);
begin
gtk_new (Object.F, "ajout du fichier", action_Save, null);
end Stop_Program;
end P_fichier;
main_program.adb
with gtk.main; use gtk.main;
with gtk.window; use gtk.window;
with gtk.button; use gtk.button;
with P_fichier; use P_fichier;
Procedure main_Program is
win : gtk_window;
bouton : gtk_button;
begin
init;
gtk_new (win);
win.set_default_size (600,400);
gtk_new (bouton,"ouvrir le fichier");
declare
Object : T_Type;
begin
P_fichier.callback.connect (bouton,s signal_clicked, callback.to_marshaller (stop_program'
access, Object, false );
end ;
win.Add (bouton);
win.show_all;
main;
end main_program;
voila le probleme est que le programme affiche le meme message d'erreur que precedent pourtant j'ai bien mis Stop_Program dans un fichier separe. mais je ne comprend pas j'ai essayé avec Object_connect mais c'est toujours pareil.
A première lecture du programme, le problème n'est plus avec
stop_program mais avec Object.
Object n'existe qu'entre declare et le end correspondant.
Il n'est donc pas possible de l'utiliser dans une callback.

Nicolas
Danielle Mandi Mayagha
2021-09-21 14:31:20 UTC
Permalink
Post by DrPi
Bonjour,
...
Post by Danielle Mandi Mayagha
Salut désolé encore si je dérange mais j'ai un second souci que j'arrive pas à résoudre( voila je donne un exemple du code apres j'explique le probleme)
ficfier.ads
with Gtk.File_chooser_dialog; use gtk.file_file_chooser_dialog;
with gtk.widget; use gtk.widget;
with gtk.handlers;
package P_fichier is
type T_Type is record
F : Gtk_file_chooser_dialog;
end record;
package Callback is new gtk.handlers.user_callback (gtk_widget_record, P_fichier.T_Type);
use Callback;
Procedure Stop_Program ( emetteur : access gtk_widget_record;
object : out P_fichier.T_Type );
end P_fichier;
fichier.adb
package body P_fichier is
Procedure Stop_Program is (emetteur : access gtk_widget_record;
object : out P_fichier.T_type ) is
pragma Unreferenced (emetteur);
begin
gtk_new (Object.F, "ajout du fichier", action_Save, null);
end Stop_Program;
end P_fichier;
main_program.adb
with gtk.main; use gtk.main;
with gtk.window; use gtk.window;
with gtk.button; use gtk.button;
with P_fichier; use P_fichier;
Procedure main_Program is
win : gtk_window;
bouton : gtk_button;
begin
init;
gtk_new (win);
win.set_default_size (600,400);
gtk_new (bouton,"ouvrir le fichier");
declare
Object : T_Type;
begin
P_fichier.callback.connect (bouton,s signal_clicked, callback.to_marshaller (stop_program'
access, Object, false );
end ;
win.Add (bouton);
win.show_all;
main;
end main_program;
voila le probleme est que le programme affiche le meme message d'erreur que precedent pourtant j'ai bien mis Stop_Program dans un fichier separe. mais je ne comprend pas j'ai essayé avec Object_connect mais c'est toujours pareil.
A première lecture du programme, le problème n'est plus avec
stop_program mais avec Object.
Object n'existe qu'entre declare et le end correspondant.
Il n'est donc pas possible de l'utiliser dans une callback.
Nicolas
Ah j'ai déjà essayé cela mais ça ne marche toujours pas
Thomas
2022-01-20 20:23:00 UTC
Permalink
Post by Danielle Mandi Mayagha
Ah j'ai déjà essayé cela mais ça ne marche toujours pas
à cette étape, nous avons besoin d'avoir des détails sur ce qui ne va
pas.
les messages d'erreur du compilateur indiquent ce qu'il reste comme
erreurs à résoudre, même si tu ne sais pas encore les interpréter.

ta seule phrase de réponse est insuffisante pour nous permettre de
savoir dans quelle direction prolonger notre aide.

(et tu ne nous a pas dit non plus si la réponse de Ludovic Brenta est
suffisante.
c'est tjr agréable pour les contributeurs de savoir que leur
contribution a rendu service, qu'elle est complète et que tu n'as plus
besoin de complément pour l'instant :-) )
--
RAPID maintainer
http://savannah.nongnu.org/projects/rapid/
Ludovic Brenta
2021-09-21 17:09:37 UTC
Permalink
Post by Danielle Mandi Mayagha
package Callback is new gtk.handlers.user_callback (gtk_widget_record, P_fichier.T_Type);
use Callback;
Procedure Stop_Program ( emetteur : access gtk_widget_record;
object : out P_fichier.T_Type );
Cette procédure n'obéit pas au type Gtk.Handlers.User_Callback.Handler:

type Handler is access procedure
(Widget : access Widget_Type'Class; -- OK
Params : Glib.Values.GValues; -- ignoré
User_Data : User_Type); -- pas OK, tu as dit "out P_Fichier.T_Type"

À mon avis tu peux simplifier ton programme. Tu n'as pas besoin d'un
type User_Data. Si tu veux ouvrir un fichier, tu peux créer le dialogue
comme variable locale dans ta procédure:

package body P is
procedure On_File_Open (Button : Gtk.Button.Gtk_Button) is
Dialog : Gtk_File_Chooser_Dialog;
begin
Gtk_New (Dialog);
if Dialog.Run then
-- OK, proceed with the file selected
else
-- user cancelled the dialog
end if;
end On_File_Open;
end P;

procedure Main is
Window : Gtk_Window;
Button : Gtk_Button;
begin
Init;
Gtk_New (Window);
Window.Set_Default_Size (600,400);
Gtk_New (Button, "ouvrir le fichier");
Window.Add (Button);
Button.On_Clicked (Call => P.On_File_Open'Access);
Window.Show_All;
Main;
end Main;

Maintenant, si tu veux récupérer le nom du fichier et le stocker dans
une variable non locale, je te conseille de faire une extension de type
pour ta *fenêtre*:

package Main_Window is
type Record_T is new Gtk.Window.Gtk_Window_Record with private;
type T is access all Record_T'Class;
procedure Gtk_New (Window : out T);
private
type Record_T is new Gtk.Window.Gtk_Window_Record with record
File_Name : Gtk.Label.Gtk_Label;
end record;
end Main_Window;

package body Main_Window is
procedure On_File_Open (Self : access Glib.Object.GObject_Record'Class) is
-- Conformant with Gtk.Button.Cb_GObject_Void
Window : T := T (Self);
Dialog : Gtk_File_Chooser_Dialog;
begin
Gtk_New (Dialog);
if Dialog.Run then
-- OK, proceed with the file selected
Window.Label.Set_Text (Dialog.Get_Filename);
else
-- user cancelled the dialog
Window.Label.Set_Text ("");
end if;
end On_File_Open;

procedure Gtk_New (Window : out T) is
Button : Gtk.Button.Gtk_Button;
begin
Gtk.Window.Gtk_New (Window);
Window.Set_Default_Size (600,400);
Gtk_New (Button, "ouvrir le fichier");
Window.Add (Button);
Button.On_Clicked (Call => On_File_Open'Access, Slot => Window);
-- On_File_Open will receive the specified Window, not the button, as its Self parameter
Gtk_New (Window.Label, "");
Window.Add (Label);
Window.Show_All;
end Gtk_New;
end Main_Window;

procedure Main is
Window : Main_Window.T;
begin
Gtk.Main.Init;
Main_Window.Gtk_New (Window);
Gtk.Main.Main;
end Main;
--
Ludovic Brenta.
The senior support staff transitions our supportive and/or market-based transformation process round-the-clock.
Loading...