I started to write an OpenGL library and was only a couple of dozen lines into the pir when I remembered the documentation about callbacks in docs/pdds/draft/pdd16_native_call.pod .
Currently there are only two signatures supported on callbacks: one with user_data and extern_data and the other with extern_data and user_data (the positions are all that is different). These are nice and general functions and work well because the user_data is/should be opaque to the calling C function, the user_data provides a place to store the PMC, and the user_data is used to lookup the interpreter that should be used to run the sub stored in the PMC. The pdd says that outside the two provided signatures, anybody wanting to implement NCI connections to callback functions will need to do some hand C coding. Hand C coding isn't at all bad, but it would be nice to have a generic mechanism for storing callbacks from C functions that don't provide a slot for opaque user_data. I was on my way to coding a solution with my meager C skills and wanted to make sure that what I was doing was sane (for some definition of the word sane). So my proposal goes something like this: - Get a new unique id from a new op called get_callback_id - Call a variant of the new_callback op, passing in the unique id - The new_callback variant stores the user data under the unique id - The callback references a unique C function that will return that unique id - When the callback is fired, the unique id is used to lookup the user_data - Any external data is parsed as needed - The registered sub is played Ok, sounds hard enough - but it gets worse. Here is how I would implement this generic callback system and what I think would be required. There will probably need to a file similar to src/call_list.txt such as src/callback_list.txt with entries similar to: 10 v v 10 v ii Where the first number is the number of functions to pre-create, and the other two parts are the return type and signature. I'd rather not have the number be hardcoded and go with a jit solution or some other solution for runtime C function generation - but I'm not aware of anything else that would work besides pre-compiled C functions. I think it would be nice if libraries could generate/compile the needed functions independent of anything hardcoded (and that goes for call_list.txt too for that matter). The entires in callback_list.txt would generate functions similar to the following in nci.c # parrot callback functions void pcbf_v_JV_0(void) # depending up signature void pcbf_v_JV_1(void) ... void pcbf_v_JV_9(void) I would then add two more ops (I shudder to say that - I'm not sure if adding ops is a frowned upon thing). Those ops are (I haven't played with it to know if this is the right format): op get_callback_id(out INT, in STR) # the output is a unique INT for the given signature in STR # it would fail if called more times than the 10 listed # in callback_list.txt (unless a jit solution could be implemented) op delete_callback_id(in INT, in STR) # deletes the user_data in the storage structure, freeing it # for later use Currently the following op is defined in src/ops/core.ops: op new_callback(out PMC, invar PMC, invar PMC, in STR) I want to add one more variant of this op op new_callback(out PMC, in INT, invar PMC, invar PNC, in STR) Another piece that is required is that there be a global ResizablePMCArray (actually there may be multiple based on the registered signatures). Again, I can hear everybody shuddering at the mention of a global. I don't know enought about parrot yet to know if it should be a true global variable, or if it should be tied to an interpreter, or if there is somewhere I should register the PMC with, or if there is already a central structure that would take care of functions like this. My questions are: - Does anybody else want a generic callback function mechanism in NCI? - Is this a relatively sane/clean way to do it? - Is there a better way to generate the functions for each signature? - What is the right way to store that global user_data until the callbacks are fired? I don't think I've been clear enough, but I'll post and then answer questions. I think that it would be good to have something that libraries could use without having to drop down to the C level - I just am not sure if this is too much bloat to implement it. Paul Seamons I've been here all along - I'm just really quiet.