So, I have some c code that saves an svalue:
struct signal_data { struct svalue cb; struct svalue args; int signal_id; };
struct signal_data *sv; sv= /* allocated structure */ assign_svalue_no_free(&sv->cb,from_svalue); assign_svalue_no_free(&sv->args,arg_svalue);
that is sent to a function as the data for a callback, and the callback is something like this:
int pgtk2_action_callback(GtkAction *action, struct signal_data *d) { int res; push_gobject(action); push_svalue(&d->args); apply_svalue(&d->cb,2); res=Pike_sp[-1].u.integer; pop_stack(); return res; }
I have in my pike code something like this:
string filedata="test data";
int main(...) { /* init gtk, set up stuff, including something that uses filedata which gets passed to a function that assigns it, above */
return -1; // start backend }
Now, the gtk main loop runs (through the backend). I have a load routine that loads the contents of a file into filedata. Then I use the menu to select the menu option, that had filedata as an argument to be passed to the callback.
The problem is that the callback seems to get the original value of the svalue that filedata was, not the new value:
string filedat="this is a string",filename;
array menu_actions=({ ([ "name": "FileMenu", "label": "_File" ]), ([ "name": "FileOpen", "label": "_Open D64", "callback": file_open_menu, "data": 0]), ([ "name": "FileQuit", "label": "_Quit", "callback": file_quit_menu, "data": 0 ]), ([ "name": "ViewMenu", "label": "_View" ]), ([ "name": "ShowBAM", "label": "Show _BAM", "callback": show_bam_menu, "data": filedat ]), ([ "name": "ShowDir", "label": "Show _Directory", "callback": show_dir_menu, "data": filedat ]), }); int show_bam_menu(object o, mixed ... args) { write("o==%O\n",o); write("args==%O\n",args); }
int show_dir_menu(object o, mixed ... args) { write("o==%O\n",o); write("args==%O\n",args); }
int file_quit_menu(mixed ... args) { write("args==%O\n",args); exit(0); } int file_open_menu(mixed ... args) { write("args==%O\n",args); array a=({ ([ "text": GTK2.STOCK_CANCEL, "id": GTK2.RESPONSE_CANCEL ]), ([ "text": GTK2.STOCK_OPEN, "id": GTK2.RESPONSE_ACCEPT ]) }); object o=GTK2.FileChooserDialog("Open D64",w,0,a); o->set_action(GTK2.FILE_CHOOSE_ACTION_OPEN); o->run(); filename=o->get_filename(); write("filename==%s\n",filename); filedat=Stdio.read_bytes(filename); o->destroy(); }
object ui,gt1,ui1;
int main(int argc, array argv) { GTK2.setup_gtk(argv);
w=GTK2.Window(GTK2.WindowToplevel); w->signal_connect("destroy",lambda() { exit(0); },0);
ui=GTK2.UiManager(); gt1=GTK2.ActionGroup("mainmenu"); gt1->add_actions(menu_actions); ui->insert_action_group(gt1,0); ui1=ui->add_ui_from_file("menu.xml"); w->add(ui->get_widget("/MenuBar"));
w->show_all();
write("actions==%O\n",gt1->list_actions()); return -1; }
gt1->add_actions(menu_actions) adds the actions, using filedat as the data. But when the callback is actually called (show_bam_menu()), filedat is still "this is a string), rather than what I set filedat to in file_open_menu(). I put debug statements in the relevant code (GTK2/source/gtkactiongroup.pre), and it shows that the arg is still the previous value, not what I set it to. It seems that when I originally set up the callback...
Hmm, I now see why, I did assign_svalue_no_free(). I don't want to get get a copy of the svalue, I actually want to reference the svalue. Or, if needed, get an indirect reference that I can deal with in the c-code to put the current, proper value in at the time.
I hope I am clear. Does anybody have an idea of what I need to do? Maybe save a reference to the proper svalue, and not a copy, and indirectly reference it later? Although I'm not sure how I would do that. Maybe use a name of a variable in the menu_actions above, have the code do a lookup on the name at the time of the callback, and get the current value instead?
-lsd
I'm not quite sure what you are trying to do, or why you are trying to do it this way, but if you need an svalue that can be modified later, you can use for example a mapping. Anyone who has a reference to the mapping will be able to see changes you make to it with the []= operator and things like m_delete().
Strings, on the other hand, are immutable, so you can not change the value of a string value you have already passed to someone.
----- Original Message ----
From: "Marcus Comstedt (ACROSS) (Hail Ilpalazzo!) @ Pike (-) developers forum" 10353@lyskom.lysator.liu.se To: pike-devel@lists.lysator.liu.se Sent: Thu, September 2, 2010 11:40:02 AM Subject: svalue problem
I'm not quite sure what you are trying to do, or why you are trying to do it this way, but if you need an svalue that can be modified later, you can use for example a mapping. Anyone who has a reference to the mapping will be able to see changes you make to it with the []= operator and things like m_delete().
Strings, on the other hand, are immutable, so you can not change the value of a string value you have already passed to someone.
Hmm, maybe that is the best thing. Someone may pass data into the callback that could be changed, so an indirect pointer, as in a mapping, probably is best.
So, when you change a string, it actually allocates a new one and assigns it to the variable, right? So the svalue (at the c level) actually changes? And the old string is freed?
Thanks
pike-devel@lists.lysator.liu.se