Its a bit complicated and brain-mangling, the more in the absence of any examples, but the current design in pdd16 seems to lack some flexibility and is IMHO missing the proper handling of the (library-provided) external_data. The latter will be passed to the Sub somehow, but what then?

Here is (I think) a more flexible approach:

1) A new opcode "callback" (or "register_cb") or such, which is working like the current dlfunc opcode:

callback (out Pcb, in Psub, in Sig)

Pcb ... NCI function object for that callback function
Psub ... Parrot Sub PMC to be called on behalf of that C callback
Sig ... Signature of the C-callback function

Sig allows additionally one special signature char "U" user-data, which is "Z" in pdd16, but I can remember <U>ser-data better ;)

So void (*PQnoticeProcessor)(void *, const char*) would have Sig "vUt" and call a Parrot function f(P, S). Pdd16 type C callback is e.g. "vpU".

2) Actually registering the callback.

  dlfunc (out Pfunc, in Plib, "func_with_cb", "vCU")
  .pcc_begin prototpyed
  .arg Pcb
  .arg P_user_data
  .nci_call Pfunc

That is instead of passing in the callback and the Parrot Sub ("CY" in pdd16) the PMC obtained from 1) is passed with signature "C". The calling signature matches again the C-function which we call.

When now calling this function the action behind the scene is the same: The passed user_data PMC is combined with the callback PMC obtained from 1) and passed on to the C function. When the C function is doing the callback, the NCI-stub generated in 1) is called, which extracts the Parrot subroutine from the passed user data and passes on the original user PMC and finally calls the PASM callback function.
But as the generated NCI stub in 1) knows the callback signature, this scheme should be appropriate for all callback functons, that have at least one "void *" user parameter to be passed on transparently.


Comments welcome,
leo



Reply via email to