X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/a0d0e21ea6ea90a22318550944fe6cb09ae10cda..01bfea8b32d3803399b0a0a7d1a0f3181d552e34:/pod/perlcall.pod diff --git a/pod/perlcall.pod b/pod/perlcall.pod index d81ee4a..4794763 100644 --- a/pod/perlcall.pod +++ b/pod/perlcall.pod @@ -4,520 +4,733 @@ perlcall - Perl calling conventions from C =head1 DESCRIPTION -B +The purpose of this document is to show you how to call Perl subroutines +directly from C, i.e., how to write I. -The purpose of this document is to show you how to write I, -i.e. how to call Perl from C. The main -focus is on how to interface back to Perl from a bit of C code that has itself -been run by Perl, i.e. the 'main' program is a Perl script; you are using it -to execute -a section of code written in C; that bit of C code wants you to do something -with a particular event, so you want a Perl sub to be executed whenever it -happens. +Apart from discussing the C interface provided by Perl for writing +callbacks the document uses a series of examples to show how the +interface actually works in practice. In addition some techniques for +coding callbacks are covered. -Examples where this is necessary include +Examples where callbacks are necessary include =over 5 -=item * +=item * An Error Handler You have created an XSUB interface to an application's C API. A fairly common feature in applications is to allow you to define a C -function that will get called whenever something nasty occurs. -What we would like is for a Perl sub to be called instead. +function that will be called whenever something nasty occurs. What we +would like is to be able to specify a Perl subroutine that will be +called instead. -=item * +=item * An Event-Driven Program -The classic example of where callbacks are used is in an event driven program -like for X-windows. -In this case your register functions to be called whenever a specific events -occur, e.g. a mouse button is pressed. +The classic example of where callbacks are used is when writing an +event driven program, such as for an X11 application. In this case +you register functions to be called whenever specific events occur, +e.g., a mouse button is pressed, the cursor moves into a window or a +menu item is selected. =back -Although the techniques described are applicable to embedding Perl -in a C program, this is not the primary goal of this document. For details -on embedding Perl in C refer to L (currently unwritten). +Although the techniques described here are applicable when embedding +Perl in a C program, this is not the primary goal of this document. +There are other details that must be considered and are specific to +embedding Perl. For details on embedding Perl in C refer to +L. + +Before you launch yourself head first into the rest of this document, +it would be a good idea to have read the following two documents--L +and L. + +=head1 THE CALL_ FUNCTIONS + +Although this stuff is easier to explain using examples, you first need +be aware of a few important definitions. + +Perl has a number of C functions that allow you to call Perl +subroutines. They are + + I32 call_sv(SV* sv, I32 flags); + I32 call_pv(char *subname, I32 flags); + I32 call_method(char *methname, I32 flags); + I32 call_argv(char *subname, I32 flags, register char **argv); + +The key function is I. All the other functions are +fairly simple wrappers which make it easier to call Perl subroutines in +special cases. At the end of the day they will all call I +to invoke the Perl subroutine. -Before you launch yourself head first into the rest of this document, it would -be a good idea to have read the following two documents - L and L. +All the I functions have a C parameter which is +used to pass a bit mask of options to Perl. This bit mask operates +identically for each of the functions. The settings available in the +bit mask are discussed in L. -This stuff is easier to explain using examples. But first here are a few -definitions anyway. +Each of the functions will now be discussed in turn. -=head2 Definitions +=over 5 + +=item call_sv + +I takes two parameters. The first, C, is an SV*. +This allows you to specify the Perl subroutine to be called either as a +C string (which has first been converted to an SV) or a reference to a +subroutine. The section, I, shows how you can make +use of I. + +=item call_pv -Perl has a number of C functions which allow you to call Perl subs. They are +The function, I, is similar to I except it +expects its first parameter to be a C char* which identifies the Perl +subroutine you want to call, e.g., C. If the +subroutine you want to call is in another package, just include the +package name in the string, e.g., C<"pkg::fred">. - I32 perl_call_sv(SV* sv, I32 flags) ; - I32 perl_call_pv(char *subname, I32 flags) ; - I32 perl_call_method(char *methname, I32 flags) ; - I32 perl_call_argv(char *subname, I32 flags, register char **argv) ; +=item call_method -The key function is I. All the other functions make use of -I to do what they do. +The function I is used to call a method from a Perl +class. The parameter C corresponds to the name of the method +to be called. Note that the class that the method belongs to is passed +on the Perl stack rather than in the parameter list. This class can be +either the name of the class (for a static method) or a reference to an +object (for a virtual method). See L for more information on +static and virtual methods and L for an example +of using I. -I takes two parameters, the first is an SV*. This allows you to -specify the Perl sub to be called either as a C string (which has first been -converted to an SV) or a reference to a -sub. Example 7, shows you how you can make use of I. -The second parameter, C, is a general purpose option command. -This parameter is common to all the I functions. -It is discussed in the next section. +=item call_argv + +I calls the Perl subroutine specified by the C string +stored in the C parameter. It also takes the usual C +parameter. The final parameter, C, consists of a NULL-terminated +list of C strings to be passed as parameters to the Perl subroutine. +See I. + +=back -The function, I, is similar as I except it -expects it's first parameter has to be a C char* which identifies the Perl -sub you want to call, e.g. C. +All the functions return an integer. This is a count of the number of +items returned by the Perl subroutine. The actual items returned by the +subroutine are stored on the Perl stack. -The function I expects its first argument to contain a -blessed reference to a class. Using that reference it looks up and calls C -from that class. See example 9. +As a general rule you should I check the return value from +these functions. Even if you are expecting only a particular number of +values to be returned from the Perl subroutine, there is nothing to +stop someone from doing something unexpected--don't say you haven't +been warned. -I calls the Perl sub specified by the C parameter. -It also takes the usual C parameter. -The final parameter, C, consists of a -list of C strings to be sent to the Perl sub. See example 8. +=head1 FLAG VALUES -All the functions return a number. This is a count of the number of items -returned by the Perl sub on the stack. +The C parameter in all the I functions is one of G_VOID, +G_SCALAR, or G_ARRAY, which indicate the call context, OR'ed together +with a bit mask of any combination of the other G_* symbols defined below. -As a general rule you should I check the return value from these -functions. -Even if you are only expecting a particular number of values to be returned -from the Perl sub, there is nothing to stop someone from doing something -unexpected - don't say you havn't been warned. +=head2 G_VOID -=head2 Flag Values +Calls the Perl subroutine in a void context. -The C parameter in all the I functions consists of any -combination of the symbols defined below, OR'ed together. +This flag has 2 effects: =over 5 -=item G_SCALAR +=item 1. -Calls the Perl sub in a scalar context. +It indicates to the subroutine being called that it is executing in +a void context (if it executes I the result will be the +undefined value). -Whatever the Perl sub actually returns, we only want a scalar. If the perl sub -does return a scalar, the return value from the I function -will be 1 or 0. If 1, then the value actually returned by the Perl sub will -be contained -on the top of the stack. -If 0, then the sub has probably called I or you have -used the G_DISCARD flag. +=item 2. -If the Perl sub returns a list, the I function will still -only return 1 or 0. If 1, then the number of elements in the list -will be stored on top of the stack. -The actual values of the list will not be accessable. +It ensures that nothing is actually returned from the subroutine. +=back -G_SCALAR is the default flag setting for all the functions. +The value returned by the I function indicates how many +items have been returned by the Perl subroutine--in this case it will +be 0. -=item G_ARRAY -Calls the Perl sub in a list context. +=head2 G_SCALAR -The return code from the I functions will indicate how -many elements of the stack are used to store the array. +Calls the Perl subroutine in a scalar context. This is the default +context flag setting for all the I functions. -=item G_DISCARD +This flag has 2 effects: -If you are not interested in the values returned by the Perl sub then setting -this flag will make Perl get rid of them automatically for you. This will take -precedence to either G_SCALAR or G_ARRAY. +=over 5 -If you do -not set this flag then you may need to explicitly get rid of temporary values. -See example 3 for details. +=item 1. -=item G_NOARGS +It indicates to the subroutine being called that it is executing in a +scalar context (if it executes I the result will be false). -If you are not passing any parameters to the Perl sub, you can save a bit of -time by setting this flag. It has the effect of of not creating the C<@_> array -for the Perl sub. +=item 2. -A point worth noting is that if this flag is specified the Perl sub called can -still access an C<@_> array from a previous Perl sub. -This functionality can be illustrated with the perl code below +It ensures that only a scalar is actually returned from the subroutine. +The subroutine can, of course, ignore the I and return a +list anyway. If so, then only the last element of the list will be +returned. - sub fred - { print "@_\n" } +=back - sub joe - { &fred } +The value returned by the I function indicates how many +items have been returned by the Perl subroutine - in this case it will +be either 0 or 1. - &joe(1,2,3) ; +If 0, then you have specified the G_DISCARD flag. + +If 1, then the item actually returned by the Perl subroutine will be +stored on the Perl stack - the section I shows how +to access this value on the stack. Remember that regardless of how +many items the Perl subroutine returns, only the last one will be +accessible from the stack - think of the case where only one value is +returned as being a list with only one element. Any other items that +were returned will not exist by the time control returns from the +I function. The section I shows an example of this behavior. + + +=head2 G_ARRAY + +Calls the Perl subroutine in a list context. + +As with G_SCALAR, this flag has 2 effects: + +=over 5 + +=item 1. + +It indicates to the subroutine being called that it is executing in a +list context (if it executes I the result will be true). + +=item 2. + +It ensures that all items returned from the subroutine will be +accessible when control returns from the I function. + +=back + +The value returned by the I function indicates how many +items have been returned by the Perl subroutine. + +If 0, then you have specified the G_DISCARD flag. + +If not 0, then it will be a count of the number of items returned by +the subroutine. These items will be stored on the Perl stack. The +section I gives an example of using the +G_ARRAY flag and the mechanics of accessing the returned items from the +Perl stack. + +=head2 G_DISCARD + +By default, the I functions place the items returned from +by the Perl subroutine on the stack. If you are not interested in +these items, then setting this flag will make Perl get rid of them +automatically for you. Note that it is still possible to indicate a +context to the Perl subroutine by using either G_SCALAR or G_ARRAY. + +If you do not set this flag then it is I important that you make +sure that any temporaries (i.e., parameters passed to the Perl +subroutine and values returned from the subroutine) are disposed of +yourself. The section I gives details of how to +dispose of these temporaries explicitly and the section I discusses the specific circumstances where you +can ignore the problem and let Perl deal with it for you. + +=head2 G_NOARGS + +Whenever a Perl subroutine is called using one of the I +functions, it is assumed by default that parameters are to be passed to +the subroutine. If you are not passing any parameters to the Perl +subroutine, you can save a bit of time by setting this flag. It has +the effect of not creating the C<@_> array for the Perl subroutine. + +Although the functionality provided by this flag may seem +straightforward, it should be used only if there is a good reason to do +so. The reason for being cautious is that, even if you have specified +the G_NOARGS flag, it is still possible for the Perl subroutine that +has been called to think that you have passed it parameters. + +In fact, what can happen is that the Perl subroutine you have called +can access the C<@_> array from a previous Perl subroutine. This will +occur when the code that is executing the I function has +itself been called from another Perl subroutine. The code below +illustrates this + + sub fred + { print "@_\n" } + + sub joe + { &fred } + + &joe(1,2,3); This will print - 1 2 3 + 1 2 3 + +What has happened is that C accesses the C<@_> array which +belongs to C. -What has happened is that C accesses the C<@_> array which belongs to C. -=item G_EVAL +=head2 G_EVAL -If the Perl sub you are calling has the ability to terminate -abnormally, e.g. by calling I or by not actually existing, and -you want to catch this type of event, specify this flag setting. It will put -an I around the sub call. +It is possible for the Perl subroutine you are calling to terminate +abnormally, e.g., by calling I explicitly or by not actually +existing. By default, when either of these events occurs, the +process will terminate immediately. If you want to trap this +type of event, specify the G_EVAL flag. It will put an I +around the subroutine call. -Whenever control returns from the I function you need to -check the C<$@> variable as you would in a normal Perl script. -See example 6 for details of how to do this. +Whenever control returns from the I function you need to +check the C<$@> variable as you would in a normal Perl script. +The value returned from the I function is dependent on +what other flags have been specified and whether an error has +occurred. Here are all the different cases that can occur: + +=over 5 + +=item * + +If the I function returns normally, then the value +returned is as specified in the previous sections. + +=item * + +If G_DISCARD is specified, the return value will always be 0. + +=item * + +If G_ARRAY is specified I an error has occurred, the return value +will always be 0. + +=item * + +If G_SCALAR is specified I an error has occurred, the return value +will be 1 and the value on the top of the stack will be I. This +means that if you have already detected the error by checking C<$@> and +you want the program to continue, you must remember to pop the I +from the stack. =back +See I for details on using G_EVAL. -=head1 EXAMPLES +=head2 G_KEEPERR + +Using the G_EVAL flag described above will always set C<$@>: clearing +it if there was no error, and setting it to describe the error if there +was an error in the called code. This is what you want if your intention +is to handle possible errors, but sometimes you just want to trap errors +and stop them interfering with the rest of the program. -Enough of the definition talk, let's have a few examples. +This scenario will mostly be applicable to code that is meant to be called +from within destructors, asynchronous callbacks, and signal handlers. +In such situations, where the code being called has little relation to the +surrounding dynamic context, the main program needs to be insulated from +errors in the called code, even if they can't be handled intelligently. +It may also be useful to do this with code for C<__DIE__> or C<__WARN__> +hooks, and C functions. -Perl provides many macros to assist in accessing the Perl stack. -These macros should always be used when interfacing to Perl internals. -Hopefully this should make the code less vulnerable to changes made to -Perl in the future. +The G_KEEPERR flag is meant to be used in conjunction with G_EVAL in +I functions that are used to implement such code, or with +C. This flag has no effect on the C functions when +G_EVAL is not used. -Another point worth noting is that in the first series of examples I have -only made use of the I function. -This has only been done to ease you into the -topic. Wherever possible, if the choice is between using I -and I, I would always try to use I. +When G_KEEPERR is used, any error in the called code will terminate the +call as usual, and the error will not propagate beyond the call (as usual +for G_EVAL), but it will not go into C<$@>. Instead the error will be +converted into a warning, prefixed with the string "\t(in cleanup)". +This can be disabled using C. If there is no error, +C<$@> will not be cleared. -The code for these examples is stored in the file F. -(Once this document settles down, all the example code will be available in the file). +Note that the G_KEEPERR flag does not propagate into inner evals; these +may still set C<$@>. -=head2 Example1: No Parameters, Nothing returned +The G_KEEPERR flag was introduced in Perl version 5.002. -This first trivial example will call a Perl sub, I, to print -out the UID of the process. +See I for an example of a situation that warrants the +use of this flag. + +=head2 Determining the Context + +As mentioned above, you can determine the context of the currently +executing subroutine in Perl with I. The equivalent test +can be made in C by using the C macro, which returns +C if you have been called in a list context, C if +in a scalar context, or C if in a void context (i.e., the +return value will not be used). An older version of this macro is +called C; in a void context it returns C instead of +C. An example of using the C macro is shown in +section I. + +=head1 EXAMPLES + +Enough of the definition talk! Let's have a few examples. + +Perl provides many macros to assist in accessing the Perl stack. +Wherever possible, these macros should always be used when interfacing +to Perl internals. We hope this should make the code less vulnerable +to any changes made to Perl in the future. + +Another point worth noting is that in the first series of examples I +have made use of only the I function. This has been done +to keep the code simpler and ease you into the topic. Wherever +possible, if the choice is between using I and +I, you should always try to use I. See +I for details. + +=head2 No Parameters, Nothing Returned + +This first trivial example will call a Perl subroutine, I, to +print out the UID of the process. sub PrintUID { - print "UID is $<\n" ; + print "UID is $<\n"; } -and here is the C to call it +and here is a C function to call it - void + static void call_PrintUID() { - dSP ; + dSP; - PUSHMARK(sp) ; - perl_call_pv("PrintUID", G_DISCARD|G_NOARGS) ; + PUSHMARK(SP); + call_pv("PrintUID", G_DISCARD|G_NOARGS); } -Simple, eh. +Simple, eh? -A few points to note about this example. +A few points to note about this example: =over 5 -=item 1. +=item 1. -We aren't passing any parameters to I so G_NOARGS -can be specified. +Ignore C and C for now. They will be discussed in +the next example. =item 2. -Ignore C and C for now. They will be discussed in the next -example. +We aren't passing any parameters to I so G_NOARGS can be +specified. -=item 3. +=item 3. We aren't interested in anything returned from I, so -G_DISCARD is specified. Even if I was changed to actually +G_DISCARD is specified. Even if I was changed to return some value(s), having specified G_DISCARD will mean that they -will be wiped by the time control returns from I. +will be wiped by the time control returns from I. -=item 4. +=item 4. -Because we specified G_DISCARD, it is not necessary to check -the value returned from I. It will always be 0. +As I is being used, the Perl subroutine is specified as a +C string. In this case the subroutine name has been 'hard-wired' into the +code. =item 5. -As I is being used, the Perl sub is specified as a C string. +Because we specified G_DISCARD, it is not necessary to check the value +returned from I. It will always be 0. =back -=head2 Example 2: Passing Parameters +=head2 Passing Parameters -Now let's make a slightly more complex example. This time we want -to call a Perl sub -which will take 2 parameters - a string (C<$s>) and an integer (C<$n>). -The sub will simply print the first C<$n> characters of the string. +Now let's make a slightly more complex example. This time we want to +call a Perl subroutine, C, which will take 2 parameters--a +string ($s) and an integer ($n). The subroutine will simply +print the first $n characters of the string. -So the Perl sub would look like this +So the Perl subroutine would look like this: sub LeftString { - my($s, $n) = @_ ; - print substr($s, 0, $n), "\n" ; + my($s, $n) = @_; + print substr($s, 0, $n), "\n"; } -The C function required to call I would look like this. +The C function required to call I would look like this: static void call_LeftString(a, b) - char * a ; - int b ; + char * a; + int b; { - dSP ; + dSP; + + ENTER; + SAVETMPS; - PUSHMARK(sp) ; + PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(a, 0))); XPUSHs(sv_2mortal(newSViv(b))); - PUTBACK ; + PUTBACK; - perl_call_pv("LeftString", G_DISCARD); - } + call_pv("LeftString", G_DISCARD); + FREETMPS; + LEAVE; + } Here are a few notes on the C function I. =over 5 -=item 1. - -The only flag specified this time is G_DISCARD. As we are passing 2 -parameters to the Perl sub this time, we have not specified G_NOARGS. - -=item 2. - -Parameters are passed to the Perl sub using the Perl stack. -This is the purpose of the code beginning with the line C and ending -with the line C. +=item 1. +Parameters are passed to the Perl subroutine using the Perl stack. +This is the purpose of the code beginning with the line C and +ending with the line C. The C declares a local copy +of the stack pointer. This local copy should B be accessed +as C. -=item 3. +=item 2. If you are going to put something onto the Perl stack, you need to know -where to put it. This is the purpose of the macro C - -it declares and initialises a local copy of the Perl stack pointer. +where to put it. This is the purpose of the macro C--it declares +and initializes a I copy of the Perl stack pointer. All the other macros which will be used in this example require you to -have used this macro. +have used this macro. -If you are calling a Perl sub directly from an XSUB function, it is -not necessary to explicitly use the C macro - it will be declared for you. +The exception to this rule is if you are calling a Perl subroutine +directly from an XSUB function. In this case it is not necessary to +use the C macro explicitly--it will be declared for you +automatically. -=item 4. +=item 3. Any parameters to be pushed onto the stack should be bracketed by the -C and C macros. -The purpose of these two macros, in this context, is to automatically count -the number of parameters you are pushing. Then whenever Perl is creating -the C<@_> array for the sub, it knows how big to make it. - -The C macro tells Perl to make a mental note of the current stack -pointer. Even if you aren't passing any parameters (like in Example 1) you must -still call the C macro before you can call any of -the I functions - Perl still needs to know that there are -no parameters. - -The C macro sets the global copy of the stack pointer to be the -same as our local copy. If we didn't do this I wouldn't -know where the two parameters we pushed were - remember that up to now -all the stack pointer manipulation we have done is with our local copy, -I the global copy. +C and C macros. The purpose of these two macros, in +this context, is to count the number of parameters you are +pushing automatically. Then whenever Perl is creating the C<@_> array for the +subroutine, it knows how big to make it. + +The C macro tells Perl to make a mental note of the current +stack pointer. Even if you aren't passing any parameters (like the +example shown in the section I) you +must still call the C macro before you can call any of the +I functions--Perl still needs to know that there are no +parameters. + +The C macro sets the global copy of the stack pointer to be +the same as our local copy. If we didn't do this, I +wouldn't know where the two parameters we pushed were--remember that +up to now all the stack pointer manipulation we have done is with our +local copy, I the global copy. -=item 5. +=item 4. Next, we come to XPUSHs. This is where the parameters actually get -pushed onto the stack. In this case we are pushing a string and an integer. +pushed onto the stack. In this case we are pushing a string and an +integer. + +See L for details +on how the XPUSH macros work. + +=item 5. + +Because we created temporary values (by means of sv_2mortal() calls) +we will have to tidy up the Perl stack and dispose of mortal SVs. + +This is the purpose of + + ENTER; + SAVETMPS; + +at the start of the function, and + + FREETMPS; + LEAVE; + +at the end. The C/C pair creates a boundary for any +temporaries we create. This means that the temporaries we get rid of +will be limited to those which were created after these calls. -See the section I in L for -details on how the XPUSH macros work. +The C/C pair will get rid of any values returned by +the Perl subroutine (see next example), plus it will also dump the +mortal SVs we have created. Having C/C at the +beginning of the code makes sure that no other mortals are destroyed. + +Think of these macros as working a bit like C<{> and C<}> in Perl +to limit the scope of local variables. + +See the section I for details of +an alternative to using these macros. =item 6. -Finally, I can now be called via the I function. +Finally, I can now be called via the I function. +The only flag specified this time is G_DISCARD. Because we are passing +2 parameters to the Perl subroutine this time, we have not specified +G_NOARGS. =back -=head2 Example 3: Returning a Scalar +=head2 Returning a Scalar -Now for an example of dealing with the values returned from a Perl sub. +Now for an example of dealing with the items returned from a Perl +subroutine. -Here is a Perl sub, I, which takes 2 integer parameters and simply -returns their sum. +Here is a Perl subroutine, I, that takes 2 integer parameters +and simply returns their sum. sub Adder { - my($a, $b) = @_ ; - $a + $b ; + my($a, $b) = @_; + $a + $b; } -As we are now concerned with the return value from I, the C function -is now a bit more complex. +Because we are now concerned with the return value from I, the C +function required to call it is now a bit more complex. static void call_Adder(a, b) - int a ; - int b ; + int a; + int b; { - dSP ; - int count ; + dSP; + int count; - ENTER ; + ENTER; SAVETMPS; - PUSHMARK(sp) ; + PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); - PUTBACK ; + PUTBACK; - count = perl_call_pv("Adder", G_SCALAR); + count = call_pv("Adder", G_SCALAR); - SPAGAIN ; + SPAGAIN; - if (count != 1) - croak("Big trouble\n") ; + if (count != 1) + croak("Big trouble\n"); - printf ("The sum of %d and %d is %d\n", a, b, POPi) ; + printf ("The sum of %d and %d is %d\n", a, b, POPi); - PUTBACK ; - FREETMPS ; - LEAVE ; + PUTBACK; + FREETMPS; + LEAVE; } - Points to note this time are =over 5 -=item 1. - -The only flag specified this time was G_SCALAR. That means the @_ array -will be created and that the value returned by I will still -exist after the call to I. - +=item 1. +The only flag specified this time was G_SCALAR. That means that the C<@_> +array will be created and that the value returned by I will +still exist after the call to I. =item 2. -Because we are interested in what is returned from I we cannot specify -G_DISCARD. This means that we will have to tidy up the Perl stack and dispose -of any temporary values ourselves. This is the purpose of - - ENTER ; - SAVETMPS ; - -at the start of the function, and - - FREETMPS ; - LEAVE ; - -at the end. The C/C pair creates a boundary for any -temporaries we create. -This means that the temporaries we get rid of will be limited to those which -were created after these calls. - -The C/C pair will get rid of any values returned by the Perl -sub, plus it will also dump the mortal SV's we created. -Having C/C at the beginning -of the code makes sure that no other mortals are destroyed. - -=item 3. - The purpose of the macro C is to refresh the local copy of the stack pointer. This is necessary because it is possible that the memory -allocated to the Perl stack has been re-allocated whilst in the I -call. +allocated to the Perl stack has been reallocated during the +I call. -If you are making use of the Perl stack pointer in your code you must always -refresh the your local copy using SPAGAIN whenever you make use of -of the I functions or any other Perl internal function. +If you are making use of the Perl stack pointer in your code you must +always refresh the local copy using SPAGAIN whenever you make use +of the I functions or any other Perl internal function. -=item 4. +=item 3. -Although only a single value was expected to be returned from I, it is -still good practice to check the return code from I anyway. +Although only a single value was expected to be returned from I, +it is still good practice to check the return code from I +anyway. -Expecting a single value is not quite the same as knowing that there will -be one. If someone modified I to return a list and we didn't check -for that possibility and take appropriate action the Perl stack would end -up in an inconsistant state. That is something you I don't want -to ever happen. +Expecting a single value is not quite the same as knowing that there +will be one. If someone modified I to return a list and we +didn't check for that possibility and take appropriate action the Perl +stack would end up in an inconsistent state. That is something you +I don't want to happen ever. -=item 5. +=item 4. -The C macro is used here to pop the return value from the stack. In this -case we wanted an integer, so C was used. +The C macro is used here to pop the return value from the stack. +In this case we wanted an integer, so C was used. -Here is the complete list of POP macros available, along with the types they -return. +Here is the complete list of POP macros available, along with the types +they return. - POPs SV - POPp pointer - POPn double - POPi integer - POPl long + POPs SV + POPp pointer + POPn double + POPi integer + POPl long -=item 6. +=item 5. -The final C is used to leave the Perl stack in a consistant state -before exiting the function. This is -necessary because when we popped the return value from the stack with C it -only updated our local copy of the stack pointer. Remember, C sets the -global stack pointer to be the same as our local copy. +The final C is used to leave the Perl stack in a consistent +state before exiting the function. This is necessary because when we +popped the return value from the stack with C it updated only our +local copy of the stack pointer. Remember, C sets the global +stack pointer to be the same as our local copy. =back -=head2 Example 4: Returning a list of values +=head2 Returning a List of Values -Now, let's extend the previous example to return both the sum of the parameters -and the difference. +Now, let's extend the previous example to return both the sum of the +parameters and the difference. -Here is the Perl sub +Here is the Perl subroutine sub AddSubtract { - my($a, $b) = @_ ; - ($a+$b, $a-$b) ; + my($a, $b) = @_; + ($a+$b, $a-$b); } - and this is the C function static void call_AddSubtract(a, b) - int a ; - int b ; + int a; + int b; { - dSP ; - int count ; + dSP; + int count; - ENTER ; + ENTER; SAVETMPS; - PUSHMARK(sp) ; + PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); - PUTBACK ; + PUTBACK; - count = perl_call_pv("AddSubtract", G_ARRAY); + count = call_pv("AddSubtract", G_ARRAY); - SPAGAIN ; + SPAGAIN; - if (count != 2) - croak("Big trouble\n") ; + if (count != 2) + croak("Big trouble\n"); - printf ("%d - %d = %d\n", a, b, POPi) ; - printf ("%d + %d = %d\n", a, b, POPi) ; + printf ("%d - %d = %d\n", a, b, POPi); + printf ("%d + %d = %d\n", a, b, POPi); - PUTBACK ; - FREETMPS ; - LEAVE ; + PUTBACK; + FREETMPS; + LEAVE; } +If I is called like this + + call_AddSubtract(7, 4); + +then here is the output + + 7 - 4 = 3 + 7 + 4 = 11 Notes @@ -525,314 +738,1199 @@ Notes =item 1. -We wanted array context, so we used G_ARRAY. +We wanted list context, so G_ARRAY was used. =item 2. -Not surprisingly there are 2 POPi's this time because we were retrieving 2 -values from the stack. The main point to note is that they came off the stack in -reverse order. +Not surprisingly C is used twice this time because we were +retrieving 2 values from the stack. The important thing to note is that +when using the C macros they come off the stack in I +order. =back -=head2 Example 5: Returning Data from Perl via the parameter list +=head2 Returning a List in a Scalar Context + +Say the Perl subroutine in the previous section was called in a scalar +context, like this -It is also possible to return values directly via the parameter list - -whether it is actually desirable to do it is another matter entirely. + static void + call_AddSubScalar(a, b) + int a; + int b; + { + dSP; + int count; + int i; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(a))); + XPUSHs(sv_2mortal(newSViv(b))); + PUTBACK; + + count = call_pv("AddSubtract", G_SCALAR); + + SPAGAIN; + + printf ("Items Returned = %d\n", count); + + for (i = 1; i <= count; ++i) + printf ("Value %d = %d\n", i, POPi); + + PUTBACK; + FREETMPS; + LEAVE; + } -The Perl sub, I, below takes 2 parameters and increments each. +The other modification made is that I will print the +number of items returned from the Perl subroutine and their value (for +simplicity it assumes that they are integer). So if +I is called + + call_AddSubScalar(7, 4); + +then the output will be + + Items Returned = 1 + Value 1 = 3 + +In this case the main point to note is that only the last item in the +list is returned from the subroutine. I actually made it back to +I. + + +=head2 Returning Data from Perl via the Parameter List + +It is also possible to return values directly via the parameter +list--whether it is actually desirable to do it is another matter entirely. + +The Perl subroutine, I, below takes 2 parameters and increments +each directly. sub Inc { - ++ $_[0] ; - ++ $_[1] ; + ++ $_[0]; + ++ $_[1]; } and here is a C function to call it. static void call_Inc(a, b) - int a ; - int b ; + int a; + int b; { - dSP ; - int count ; - SV * sva ; - SV * svb ; + dSP; + int count; + SV * sva; + SV * svb; - ENTER ; + ENTER; SAVETMPS; - sva = sv_2mortal(newSViv(a)) ; - svb = sv_2mortal(newSViv(b)) ; + sva = sv_2mortal(newSViv(a)); + svb = sv_2mortal(newSViv(b)); - PUSHMARK(sp) ; + PUSHMARK(SP); XPUSHs(sva); XPUSHs(svb); - PUTBACK ; + PUTBACK; - count = perl_call_pv("Inc", G_DISCARD); + count = call_pv("Inc", G_DISCARD); if (count != 0) - croak ("call_Inc : expected 0 return value from 'Inc', got %d\n", count) ; + croak ("call_Inc: expected 0 values from 'Inc', got %d\n", + count); - printf ("%d + 1 = %d\n", a, SvIV(sva)) ; - printf ("%d + 1 = %d\n", b, SvIV(svb)) ; + printf ("%d + 1 = %d\n", a, SvIV(sva)); + printf ("%d + 1 = %d\n", b, SvIV(svb)); - FREETMPS ; - LEAVE ; + FREETMPS; + LEAVE; } +To be able to access the two parameters that were pushed onto the stack +after they return from I it is necessary to make a note +of their addresses--thus the two variables C and C. - -To be able to access the two parameters that were pushed onto the stack -after they return from I it is necessary to make a note of -their addresses - thus the two variables C and C. - -The reason this is necessary is that -the area of the Perl stack which held them -will very likely have been overwritten by something else by the time control -returns from I. +The reason this is necessary is that the area of the Perl stack which +held them will very likely have been overwritten by something else by +the time control returns from I. -=head2 Example 6: Using G_EVAL - -Now an example using G_EVAL. Below is a Perl sub which computes the -difference of its 2 parameters. If this would result in a negative result, -the sub calls I. +=head2 Using G_EVAL +Now an example using G_EVAL. Below is a Perl subroutine which computes +the difference of its 2 parameters. If this would result in a negative +result, the subroutine calls I. sub Subtract { - my ($a, $b) = @_ ; + my ($a, $b) = @_; - die "death can be fatal\n" if $a < $b ; + die "death can be fatal\n" if $a < $b; - $a - $b ; + $a - $b; } and some C to call it static void call_Subtract(a, b) - int a ; - int b ; + int a; + int b; { - dSP ; - int count ; - SV * sv ; + dSP; + int count; - ENTER ; + ENTER; SAVETMPS; - PUSHMARK(sp) ; + PUSHMARK(SP); XPUSHs(sv_2mortal(newSViv(a))); XPUSHs(sv_2mortal(newSViv(b))); - PUTBACK ; + PUTBACK; + + count = call_pv("Subtract", G_EVAL|G_SCALAR); + + SPAGAIN; + + /* Check the eval first */ + if (SvTRUE(ERRSV)) + { + printf ("Uh oh - %s\n", SvPV_nolen(ERRSV)); + POPs; + } + else + { + if (count != 1) + croak("call_Subtract: wanted 1 value from 'Subtract', got %d\n", + count); + + printf ("%d - %d = %d\n", a, b, POPi); + } + + PUTBACK; + FREETMPS; + LEAVE; + } + +If I is called thus - count = perl_call_pv("Subtract", G_EVAL|G_SCALAR); + call_Subtract(4, 5) - /* Check the eval first */ - sv = GvSV(gv_fetchpv("@", TRUE, SVt_PV)); - if (SvTRUE(sv)) - printf ("Uh oh - %s\n", SvPV(sv, na)) ; +the following will be printed - SPAGAIN ; + Uh oh - death can be fatal - if (count != 1) - croak ("call_Subtract : expected 1 return value from 'Subtract', got %d\n", count) ; +Notes +=over 5 - printf ("%d - %d = %d\n", a, b, POPi) ; +=item 1. - PUTBACK ; - FREETMPS ; - LEAVE ; +We want to be able to catch the I so we have used the G_EVAL +flag. Not specifying this flag would mean that the program would +terminate immediately at the I statement in the subroutine +I. +=item 2. + +The code + + if (SvTRUE(ERRSV)) + { + printf ("Uh oh - %s\n", SvPV_nolen(ERRSV)); + POPs; } -If I is called thus +is the direct equivalent of this bit of Perl - call_Subtract(4, 5) + print "Uh oh - $@\n" if $@; -the following will be printed +C is a perl global of type C that points to the +symbol table entry containing the error. C therefore +refers to the C equivalent of C<$@>. + +=item 3. - Uh oh - death can be fatal +Note that the stack is popped using C in the block where +C is true. This is necessary because whenever a +I function invoked with G_EVAL|G_SCALAR returns an error, +the top of the stack holds the value I. Because we want the +program to continue after detecting this error, it is essential that +the stack be tidied up by removing the I. -Notes +=back + + +=head2 Using G_KEEPERR + +Consider this rather facetious example, where we have used an XS +version of the call_Subtract example above inside a destructor: + + package Foo; + sub new { bless {}, $_[0] } + sub Subtract { + my($a,$b) = @_; + die "death can be fatal" if $a < $b; + $a - $b; + } + sub DESTROY { call_Subtract(5, 4); } + sub foo { die "foo dies"; } + + package main; + { + my $foo = Foo->new; + eval { $foo->foo }; + } + print "Saw: $@" if $@; # should be, but isn't + +This example will fail to recognize that an error occurred inside the +C. Here's why: the call_Subtract code got executed while perl +was cleaning up temporaries when exiting the outer braced block, and because +call_Subtract is implemented with I using the G_EVAL +flag, it promptly reset C<$@>. This results in the failure of the +outermost test for C<$@>, and thereby the failure of the error trap. + +Appending the G_KEEPERR flag, so that the I call in +call_Subtract reads: + + count = call_pv("Subtract", G_EVAL|G_SCALAR|G_KEEPERR); + +will preserve the error and restore reliable error handling. + +=head2 Using call_sv + +In all the previous examples I have 'hard-wired' the name of the Perl +subroutine to be called from C. Most of the time though, it is more +convenient to be able to specify the name of the Perl subroutine from +within the Perl script. + +Consider the Perl code below + + sub fred + { + print "Hello there\n"; + } + + CallSubPV("fred"); + +Here is a snippet of XSUB which defines I. + + void + CallSubPV(name) + char * name + CODE: + PUSHMARK(SP); + call_pv(name, G_DISCARD|G_NOARGS); + +That is fine as far as it goes. The thing is, the Perl subroutine +can be specified as only a string, however, Perl allows references +to subroutines and anonymous subroutines. +This is where I is useful. + +The code below for I is identical to I except +that the C parameter is now defined as an SV* and we use +I instead of I. + + void + CallSubSV(name) + SV * name + CODE: + PUSHMARK(SP); + call_sv(name, G_DISCARD|G_NOARGS); + +Because we are using an SV to call I the following can all be used: + + CallSubSV("fred"); + CallSubSV(\&fred); + $ref = \&fred; + CallSubSV($ref); + CallSubSV( sub { print "Hello there\n" } ); + +As you can see, I gives you much greater flexibility in +how you can specify the Perl subroutine. + +You should note that, if it is necessary to store the SV (C in the +example above) which corresponds to the Perl subroutine so that it can +be used later in the program, it not enough just to store a copy of the +pointer to the SV. Say the code above had been like this: + + static SV * rememberSub; + + void + SaveSub1(name) + SV * name + CODE: + rememberSub = name; + + void + CallSavedSub1() + CODE: + PUSHMARK(SP); + call_sv(rememberSub, G_DISCARD|G_NOARGS); + +The reason this is wrong is that, by the time you come to use the +pointer C in C, it may or may not still refer +to the Perl subroutine that was recorded in C. This is +particularly true for these cases: + + SaveSub1(\&fred); + CallSavedSub1(); + + SaveSub1( sub { print "Hello there\n" } ); + CallSavedSub1(); + +By the time each of the C statements above has been executed, +the SV*s which corresponded to the parameters will no longer exist. +Expect an error message from Perl of the form + + Can't use an undefined value as a subroutine reference at ... + +for each of the C lines. + +Similarly, with this code + + $ref = \&fred; + SaveSub1($ref); + $ref = 47; + CallSavedSub1(); + +you can expect one of these messages (which you actually get is dependent on +the version of Perl you are using) + + Not a CODE reference at ... + Undefined subroutine &main::47 called ... + +The variable $ref may have referred to the subroutine C +whenever the call to C was made but by the time +C gets called it now holds the number C<47>. Because we +saved only a pointer to the original SV in C, any changes to +$ref will be tracked by the pointer C. This means that +whenever C gets called, it will attempt to execute the +code which is referenced by the SV* C. In this case +though, it now refers to the integer C<47>, so expect Perl to complain +loudly. + +A similar but more subtle problem is illustrated with this code: + + $ref = \&fred; + SaveSub1($ref); + $ref = \&joe; + CallSavedSub1(); + +This time whenever C gets called it will execute the Perl +subroutine C (assuming it exists) rather than C as was +originally requested in the call to C. + +To get around these problems it is necessary to take a full copy of the +SV. The code below shows C modified to do that. + + static SV * keepSub = (SV*)NULL; + + void + SaveSub2(name) + SV * name + CODE: + /* Take a copy of the callback */ + if (keepSub == (SV*)NULL) + /* First time, so create a new SV */ + keepSub = newSVsv(name); + else + /* Been here before, so overwrite */ + SvSetSV(keepSub, name); + + void + CallSavedSub2() + CODE: + PUSHMARK(SP); + call_sv(keepSub, G_DISCARD|G_NOARGS); + +To avoid creating a new SV every time C is called, +the function first checks to see if it has been called before. If not, +then space for a new SV is allocated and the reference to the Perl +subroutine C is copied to the variable C in one +operation using C. Thereafter, whenever C is called, +the existing SV, C, is overwritten with the new value using +C. + +=head2 Using call_argv + +Here is a Perl subroutine which prints whatever parameters are passed +to it. + + sub PrintList + { + my(@list) = @_; + + foreach (@list) { print "$_\n" } + } + +And here is an example of I which will call +I. + + static char * words[] = {"alpha", "beta", "gamma", "delta", NULL}; + + static void + call_PrintList() + { + dSP; + + call_argv("PrintList", G_DISCARD, words); + } + +Note that it is not necessary to call C in this instance. +This is because I will do it for you. + +=head2 Using call_method + +Consider the following Perl code: + + { + package Mine; + + sub new + { + my($type) = shift; + bless [@_] + } + + sub Display + { + my ($self, $index) = @_; + print "$index: $$self[$index]\n"; + } + + sub PrintID + { + my($class) = @_; + print "This is Class $class version 1.0\n"; + } + } + +It implements just a very simple class to manage an array. Apart from +the constructor, C, it declares methods, one static and one +virtual. The static method, C, prints out simply the class +name and a version number. The virtual method, C, prints out a +single element of the array. Here is an all-Perl example of using it. + + $a = Mine->new('red', 'green', 'blue'); + $a->Display(1); + Mine->PrintID; + +will print + + 1: green + This is Class Mine version 1.0 + +Calling a Perl method from C is fairly straightforward. The following +things are required: =over 5 -=item 1. +=item * -We want to be able to catch the I so we have used the G_EVAL flag. -Not specifying this flag would mean that the program would terminate. +A reference to the object for a virtual method or the name of the class +for a static method -=item 2. +=item * + +The name of the method + +=item * -The code +Any other parameters specific to the method - sv = GvSV(gv_fetchpv("@", TRUE, SVt_PV)); - if (SvTRUE(sv)) - printf ("Uh oh - %s\n", SvPVx(sv, na)) ; +=back + +Here is a simple XSUB which illustrates the mechanics of calling both +the C and C methods from C. + + void + call_Method(ref, method, index) + SV * ref + char * method + int index + CODE: + PUSHMARK(SP); + XPUSHs(ref); + XPUSHs(sv_2mortal(newSViv(index))); + PUTBACK; + + call_method(method, G_DISCARD); + + void + call_PrintID(class, method) + char * class + char * method + CODE: + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv(class, 0))); + PUTBACK; + + call_method(method, G_DISCARD); + + +So the methods C and C can be invoked like this: + + $a = Mine->new('red', 'green', 'blue'); + call_Method($a, 'Display', 1); + call_PrintID('Mine', 'PrintID'); + +The only thing to note is that, in both the static and virtual methods, +the method name is not passed via the stack--it is used as the first +parameter to I. + +=head2 Using GIMME_V + +Here is a trivial XSUB which prints the context in which it is +currently executing. -is the equivalent of this bit of Perl + void + PrintContext() + CODE: + I32 gimme = GIMME_V; + if (gimme == G_VOID) + printf ("Context is Void\n"); + else if (gimme == G_SCALAR) + printf ("Context is Scalar\n"); + else + printf ("Context is Array\n"); + +And here is some Perl to test it. + + PrintContext; + $a = PrintContext; + @a = PrintContext; + +The output from that will be - print "Uh oh - $@\n" if $@ ; + Context is Void + Context is Scalar + Context is Array +=head2 Using Perl to Dispose of Temporaries +In the examples given to date, any temporaries created in the callback +(i.e., parameters passed on the stack to the I function or +values returned via the stack) have been freed by one of these methods: + +=over 5 + +=item * + +Specifying the G_DISCARD flag with I + +=item * + +Explicitly using the C/C--C/C pairing =back +There is another method which can be used, namely letting Perl do it +for you automatically whenever it regains control after the callback +has terminated. This is done by simply not using the + + ENTER; + SAVETMPS; + ... + FREETMPS; + LEAVE; + +sequence in the callback (and not, of course, specifying the G_DISCARD +flag). + +If you are going to use this method you have to be aware of a possible +memory leak which can arise under very specific circumstances. To +explain these circumstances you need to know a bit about the flow of +control between Perl and the callback routine. + +The examples given at the start of the document (an error handler and +an event driven program) are typical of the two main sorts of flow +control that you are likely to encounter with callbacks. There is a +very important distinction between them, so pay attention. + +In the first example, an error handler, the flow of control could be as +follows. You have created an interface to an external library. +Control can reach the external library like this + + perl --> XSUB --> external library + +Whilst control is in the library, an error condition occurs. You have +previously set up a Perl callback to handle this situation, so it will +get executed. Once the callback has finished, control will drop back to +Perl again. Here is what the flow of control will be like in that +situation + + perl --> XSUB --> external library + ... + error occurs + ... + external library --> call_* --> perl + | + perl <-- XSUB <-- external library <-- call_* <----+ + +After processing of the error using I is completed, +control reverts back to Perl more or less immediately. + +In the diagram, the further right you go the more deeply nested the +scope is. It is only when control is back with perl on the extreme +left of the diagram that you will have dropped back to the enclosing +scope and any temporaries you have left hanging around will be freed. + +In the second example, an event driven program, the flow of control +will be more like this + + perl --> XSUB --> event handler + ... + event handler --> call_* --> perl + | + event handler <-- call_* <----+ + ... + event handler --> call_* --> perl + | + event handler <-- call_* <----+ + ... + event handler --> call_* --> perl + | + event handler <-- call_* <----+ + +In this case the flow of control can consist of only the repeated +sequence + + event handler --> call_* --> perl + +for practically the complete duration of the program. This means that +control may I drop back to the surrounding scope in Perl at the +extreme left. + +So what is the big problem? Well, if you are expecting Perl to tidy up +those temporaries for you, you might be in for a long wait. For Perl +to dispose of your temporaries, control must drop back to the +enclosing scope at some stage. In the event driven scenario that may +never happen. This means that, as time goes on, your program will +create more and more temporaries, none of which will ever be freed. As +each of these temporaries consumes some memory your program will +eventually consume all the available memory in your system--kapow! + +So here is the bottom line--if you are sure that control will revert +back to the enclosing Perl scope fairly quickly after the end of your +callback, then it isn't absolutely necessary to dispose explicitly of +any temporaries you may have created. Mind you, if you are at all +uncertain about what to do, it doesn't do any harm to tidy up anyway. + + +=head2 Strategies for Storing Callback Context Information + + +Potentially one of the trickiest problems to overcome when designing a +callback interface can be figuring out how to store the mapping between +the C callback function and the Perl equivalent. + +To help understand why this can be a real problem first consider how a +callback is set up in an all C environment. Typically a C API will +provide a function to register a callback. This will expect a pointer +to a function as one of its parameters. Below is a call to a +hypothetical function C which registers the C function +to get called when a fatal error occurs. + + register_fatal(cb1); + +The single parameter C is a pointer to a function, so you must +have defined C in your code, say something like this + + static void + cb1() + { + printf ("Fatal Error\n"); + exit(1); + } -=head2 Example 7: Using perl_call_sv +Now change that to call a Perl subroutine instead -In all the previous examples I have 'hard-wried' the name of the Perl sub to -be called from C. -Sometimes though, it is necessary to be able to specify the name -of the Perl sub from within the Perl script. + static SV * callback = (SV*)NULL; -Consider the Perl code below + static void + cb1() + { + dSP; + + PUSHMARK(SP); + + /* Call the Perl sub to process the callback */ + call_sv(callback, G_DISCARD); + } + + + void + register_fatal(fn) + SV * fn + CODE: + /* Remember the Perl sub */ + if (callback == (SV*)NULL) + callback = newSVsv(fn); + else + SvSetSV(callback, fn); + + /* register the callback with the external library */ + register_fatal(cb1); + +where the Perl equivalent of C and the callback it +registers, C, might look like this + + # Register the sub pcb1 + register_fatal(\&pcb1); + + sub pcb1 + { + die "I'm dying...\n"; + } + +The mapping between the C callback and the Perl equivalent is stored in +the global variable C. + +This will be adequate if you ever need to have only one callback +registered at any time. An example could be an error handler like the +code sketched out above. Remember though, repeated calls to +C will replace the previously registered callback +function with the new one. + +Say for example you want to interface to a library which allows asynchronous +file i/o. In this case you may be able to register a callback whenever +a read operation has completed. To be of any use we want to be able to +call separate Perl subroutines for each file that is opened. As it +stands, the error handler example above would not be adequate as it +allows only a single callback to be defined at any time. What we +require is a means of storing the mapping between the opened file and +the Perl subroutine we want to be called for that file. + +Say the i/o library has a function C which associates a C +function C with a file handle C--this assumes that it +has also provided some routine to open the file and so obtain the file +handle. + + asynch_read(fh, ProcessRead) + +This may expect the C I function of this form + + void + ProcessRead(fh, buffer) + int fh; + char * buffer; + { + ... + } + +To provide a Perl interface to this library we need to be able to map +between the C parameter and the Perl subroutine we want called. A +hash is a convenient mechanism for storing this mapping. The code +below shows a possible implementation + + static HV * Mapping = (HV*)NULL; + + void + asynch_read(fh, callback) + int fh + SV * callback + CODE: + /* If the hash doesn't already exist, create it */ + if (Mapping == (HV*)NULL) + Mapping = newHV(); + + /* Save the fh -> callback mapping */ + hv_store(Mapping, (char*)&fh, sizeof(fh), newSVsv(callback), 0); + + /* Register with the C Library */ + asynch_read(fh, asynch_read_if); + +and C could look like this + + static void + asynch_read_if(fh, buffer) + int fh; + char * buffer; + { + dSP; + SV ** sv; + + /* Get the callback associated with fh */ + sv = hv_fetch(Mapping, (char*)&fh , sizeof(fh), FALSE); + if (sv == (SV**)NULL) + croak("Internal error...\n"); + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(fh))); + XPUSHs(sv_2mortal(newSVpv(buffer, 0))); + PUTBACK; + + /* Call the Perl sub */ + call_sv(*sv, G_DISCARD); + } + +For completeness, here is C. This shows how to remove +the entry from the hash C. + + void + asynch_close(fh) + int fh + CODE: + /* Remove the entry from the hash */ + (void) hv_delete(Mapping, (char*)&fh, sizeof(fh), G_DISCARD); + + /* Now call the real asynch_close */ + asynch_close(fh); + +So the Perl interface would look like this + + sub callback1 + { + my($handle, $buffer) = @_; + } + + # Register the Perl callback + asynch_read($fh, \&callback1); + + asynch_close($fh); - sub fred - { - print "Hello there\n" ; - } +The mapping between the C callback and Perl is stored in the global +hash C this time. Using a hash has the distinct advantage that +it allows an unlimited number of callbacks to be registered. - CallSub("fred") ; +What if the interface provided by the C callback doesn't contain a +parameter which allows the file handle to Perl subroutine mapping? Say +in the asynchronous i/o package, the callback function gets passed only +the C parameter like this + void + ProcessRead(buffer) + char * buffer; + { + ... + } + +Without the file handle there is no straightforward way to map from the +C callback to the Perl subroutine. + +In this case a possible way around this problem is to predefine a +series of C functions to act as the interface to Perl, thus + + #define MAX_CB 3 + #define NULL_HANDLE -1 + typedef void (*FnMap)(); + + struct MapStruct { + FnMap Function; + SV * PerlSub; + int Handle; + }; -here is a snippet of XSUB which defines I. + static void fn1(); + static void fn2(); + static void fn3(); - void - CallSub(name) - char * name - CODE: - PUSHMARK(sp) ; - perl_call_pv(name, G_DISCARD|G_NOARGS) ; + static struct MapStruct Map [MAX_CB] = + { + { fn1, NULL, NULL_HANDLE }, + { fn2, NULL, NULL_HANDLE }, + { fn3, NULL, NULL_HANDLE } + }; + + static void + Pcb(index, buffer) + int index; + char * buffer; + { + dSP; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv(buffer, 0))); + PUTBACK; + + /* Call the Perl sub */ + call_sv(Map[index].PerlSub, G_DISCARD); + } -That is fine as far as it goes. The thing is, it only allows the Perl sub to be -specified as a string. -For perl 4 this was adequate, but Perl 5 allows references to -subs and anonymous subs. This is where I is useful. + static void + fn1(buffer) + char * buffer; + { + Pcb(0, buffer); + } -The code below for I is identical to the previous time except that the -C parameter is now defined as an SV* and we use I instead of -I. + static void + fn2(buffer) + char * buffer; + { + Pcb(1, buffer); + } - void - CallSub(name) - SV* name - CODE: - PUSHMARK(sp) ; - perl_call_sv(name, G_DISCARD|G_NOARGS) ; + static void + fn3(buffer) + char * buffer; + { + Pcb(2, buffer); + } -As we are using an SV to call I the following can all be used + void + array_asynch_read(fh, callback) + int fh + SV * callback + CODE: + int index; + int null_index = MAX_CB; - CallSub("fred") ; - Callsub(\&fred) ; - $ref = \&fred ; - CallSub($ref) ; - CallSub( sub { print "Hello there\n" } ) ; + /* Find the same handle or an empty entry */ + for (index = 0; index < MAX_CB; ++index) + { + if (Map[index].Handle == fh) + break; -As you can see, I gives you greater flexibility in how you -can specify the Perl sub. + if (Map[index].Handle == NULL_HANDLE) + null_index = index; + } -=head2 Example 8: Using perl_call_argv + if (index == MAX_CB && null_index == MAX_CB) + croak ("Too many callback functions registered\n"); -Here is a Perl sub which prints whatever parameters are passed to it. + if (index == MAX_CB) + index = null_index; - sub PrintList - { - my(@list) = @_ ; + /* Save the file handle */ + Map[index].Handle = fh; - foreach (@list) { print "$_\n" } - } + /* Remember the Perl sub */ + if (Map[index].PerlSub == (SV*)NULL) + Map[index].PerlSub = newSVsv(callback); + else + SvSetSV(Map[index].PerlSub, callback); -and here is an example of I which will call I. + asynch_read(fh, Map[index].Function); - call_PrintList - { - dSP ; - char * words[] = {"alpha", "beta", "gamma", "delta", NULL } ; + void + array_asynch_close(fh) + int fh + CODE: + int index; - perl_call_argv("PrintList", words, G_DISCARD) ; - } + /* Find the file handle */ + for (index = 0; index < MAX_CB; ++ index) + if (Map[index].Handle == fh) + break; -Note that it is not necessary to call C in this instance. This is -because I will do it for you. + if (index == MAX_CB) + croak ("could not close fh %d\n", fh); -=head2 Example 9: Using perl_call_method + Map[index].Handle = NULL_HANDLE; + SvREFCNT_dec(Map[index].PerlSub); + Map[index].PerlSub = (SV*)NULL; -[This section is under construction] + asynch_close(fh); -Consider the following Perl code +In this case the functions C, C, and C are used to +remember the Perl subroutine to be called. Each of the functions holds +a separate hard-wired index which is used in the function C to +access the C array and actually call the Perl subroutine. - { - package Mine ; +There are some obvious disadvantages with this technique. - sub new { bless [@_] } - sub Display { print $_[0][1], "\n" } - } +Firstly, the code is considerably more complex than with the previous +example. - $a = new Mine ('red', 'green', 'blue') ; - call_Display($a, 'Display') ; +Secondly, there is a hard-wired limit (in this case 3) to the number of +callbacks that can exist simultaneously. The only way to increase the +limit is by modifying the code to add more functions and then +recompiling. None the less, as long as the number of functions is +chosen with some care, it is still a workable solution and in some +cases is the only one available. -The method C just prints out the first element of the list. -Here is a XSUB implementation of I. +To summarize, here are a number of possible methods for you to consider +for storing the mapping between C and the Perl callback - void - call_Display(ref, method) - SV * ref - char * method - CODE: - PUSHMARK(sp); - XPUSHs(ref); - PUTBACK; +=over 5 - perl_call_method(method, G_DISCARD) ; +=item 1. Ignore the problem - Allow only 1 callback +For a lot of situations, like interfacing to an error handler, this may +be a perfectly adequate solution. +=item 2. Create a sequence of callbacks - hard wired limit +If it is impossible to tell from the parameters passed back from the C +callback what the context is, then you may need to create a sequence of C +callback interface functions, and store pointers to each in an array. -=head2 Strategies for storing Context Information +=item 3. Use a parameter to map to the Perl callback -[This section is under construction] +A hash is an ideal mechanism to store the mapping between C and Perl. -One of the trickiest problems to overcome when designing a callback interface -is figuring -out how to store the mapping between the C callback functions and the -Perl equivalent. +=back -Consider the following example. =head2 Alternate Stack Manipulation -[This section is under construction] -Although I have only made use of the POP* macros to access values returned -from Perl subs, it is also possible to bypass these macros and read the -stack directly. +Although I have made use of only the C macros to access values +returned from Perl subroutines, it is also possible to bypass these +macros and read the stack using the C macro (See L for a +full description of the C macro). + +Most of the time the C macros should be adequate; the main +problem with them is that they force you to process the returned values +in sequence. This may not be the most suitable way to process the +values in some cases. What we want is to be able to access the stack in +a random order. The C macro as used when coding an XSUB is ideal +for this purpose. + +The code below is the example given in the section I recoded to use C instead of C. + + static void + call_AddSubtract2(a, b) + int a; + int b; + { + dSP; + I32 ax; + int count; + + ENTER; + SAVETMPS; + + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSViv(a))); + XPUSHs(sv_2mortal(newSViv(b))); + PUTBACK; + + count = call_pv("AddSubtract", G_ARRAY); + + SPAGAIN; + SP -= count; + ax = (SP - PL_stack_base) + 1; + + if (count != 2) + croak("Big trouble\n"); + + printf ("%d + %d = %d\n", a, b, SvIV(ST(0))); + printf ("%d - %d = %d\n", a, b, SvIV(ST(1))); + + PUTBACK; + FREETMPS; + LEAVE; + } + +Notes + +=over 5 + +=item 1. + +Notice that it was necessary to define the variable C. This is +because the C macro expects it to exist. If we were in an XSUB it +would not be necessary to define C as it is already defined for +us. + +=item 2. + +The code + + SPAGAIN; + SP -= count; + ax = (SP - PL_stack_base) + 1; + +sets the stack up so that we can use the C macro. + +=item 3. + +Unlike the original coding of this example, the returned +values are not accessed in reverse order. So C refers to the +first value returned by the Perl subroutine and C +refers to the last. + +=back + +=head2 Creating and Calling an Anonymous Subroutine in C + +As we've already shown, C can be used to invoke an +anonymous subroutine. However, our example showed a Perl script +invoking an XSUB to perform this operation. Let's see how it can be +done inside our C code: + + ... + + SV *cvrv = eval_pv("sub { print 'You will not find me cluttering any namespace!' }", TRUE); + + ... -The code below is example 4 recoded to + call_sv(cvrv, G_VOID|G_NOARGS); + +C is used to compile the anonymous subroutine, which +will be the return value as well (read more about C in +L). Once this code reference is in hand, it +can be mixed in with all the previous examples we've shown. + +=head1 LIGHTWEIGHT CALLBACKS + +Sometimes you need to invoke the same subroutine repeatedly. +This usually happens with a function that acts on a list of +values, such as Perl's built-in sort(). You can pass a +comparison function to sort(), which will then be invoked +for every pair of values that needs to be compared. The first() +and reduce() functions from L follow a similar +pattern. + +In this case it is possible to speed up the routine (often +quite substantially) by using the lightweight callback API. +The idea is that the calling context only needs to be +created and destroyed once, and the sub can be called +arbitrarily many times in between. + +It is usual to pass parameters using global variables (typically +$_ for one parameter, or $a and $b for two parameters) rather +than via @_. (It is possible to use the @_ mechanism if you know +what you're doing, though there is as yet no supported API for +it. It's also inherently slower.) + +The pattern of macro calls is like this: + + dMULTICALL; /* Declare local variables */ + I32 gimme = G_SCALAR; /* context of the call: G_SCALAR, + * G_ARRAY, or G_VOID */ + + PUSH_MULTICALL(cv); /* Set up the context for calling cv, + and set local vars appropriately */ + + /* loop */ { + /* set the value(s) af your parameter variables */ + MULTICALL; /* Make the actual call */ + } /* end of loop */ + + POP_MULTICALL; /* Tear down the calling context */ + +For some concrete examples, see the implementation of the +first() and reduce() functions of List::Util 1.18. There you +will also find a header file that emulates the multicall API +on older versions of perl. =head1 SEE ALSO -L, L, L +L, L, L =head1 AUTHOR -Paul Marquess +Paul Marquess -Special thanks to the following people who assisted in the creation of the -document. +Special thanks to the following people who assisted in the creation of +the document. -Jeff Okamoto, Tim Bunce. +Jeff Okamoto, Tim Bunce, Nick Gianniotis, Steve Kelem, Gurusamy Sarathy +and Larry Wall. =head1 DATE -Version 0.4, 17th October 1994 - - +Version 1.3, 14th Apr 1997