Встроенные перловые структуры
CONTENTS
В этом разделе рассматриваются встроенные перловые структуры.
Это будет полезно не только тем,кто работает с перл,
но и всем,кому интересно внутренне устройство интерпретатора.
Perl написан на C и имеет библиотеки,которые напрямую можно
прилинковать к коду,написанному собственно на C/C++.
Для этого нужно знать,как перл хранит свои собственные структуры
и как интерпретируются перловые типы данных.
Может так случиться,что вы напишите свои расширения или модули,
для которых понадобятся специфические структуры.
На момент написания этой книги текущей версией перл была 5.002b.
b означает beta.
Здесь вы найдете примеры того,как вызывать перловые функции из си.
И наоборот,вы можете вызывать си-шные функции из перл.
Си-шные функции,которые вы захотите прилинковать к перловым библиотекам,
потребуют хидеров из перлового дистрибутива.
Вам понадобится GNU C compiler.
Если у вас его нет - идите на oak.oakland.edu
ftp.
This section covers some of the header files in your Perl distribution.
Table 25.1 provides a brief description of what the ones covered
here contain. You can track the values or specific definitions
by starting from these header files.
Table 25.1. The Perl header files.
File | Purpose
|
XSUB.h
| Defines the XSUB interface (see Chapter 27, "Writing Extensions in C," for more information)
|
av.h |
Array variable information |
config.h
| Generated when Perl is installed |
cop.h |
Glob pointers |
cv.h |
Conversion structure |
dosish.h
| Redefining stat, fstat, and fflush for DOS
|
embed.h
| For embedding Perl in C |
EXTERN.h
| Global and external variables |
form.h
| For form feed and line feed definitions |
gv.h |
Glob pointer definitions |
handy.h
| Used for embedding Perl in C |
hv.h |
Hash definitions |
INTERN.h
| Perl internal variables |
keywords.h
| For Perl keywords |
mg.h |
Definitions for using MAGIC structures
|
op.h |
Perl operators |
patchlevel.h
| For current patchlevel information
|
pp.h |
For preprocessor directives |
perl.h
| Main header for Perl |
perly.h
| For the yylex parser
|
proto.h
| Function prototypes |
regexp.h
| Regular expressions |
scope.h
| Scoping rule definitions |
sv.h |
Scalar values |
util.h
| Blank header file |
unixish.h
| For UNIX-specific definitions |
The source files in the Perl distribution are as follows. They
come with very sparse comments.
av.c |
mg.c | pp_sys.c
|
deb.c |
miniperlmain.c |
regcomp.c |
doio.c
| op.c | regexec.c
|
doop.c
| perl.c | run.c
|
dump.c
| perlmain.c |
scope.c |
globals.c
| perly.c | sv.c
|
gv.c |
pp.c | taint.c
|
hv.c |
pp_ctl.c | toke.c
|
malloc.c
| pp_hot.c | util.c
|
The name of each file gives a hint as to what the code in the
file does. Run head *.c > text
to get a list of the headers for the files.
Now that you know a little about what source files to consult,
you're ready to learn about the building blocks of Perl programs:
the variables.
Perl has three basic data types: scalars, arrays, and hashes.
Perl enables you to have references to these data types as well
as references to subroutines. Most references use scalar values
to store their values, but you can have arrays of arrays, arrays
of references, and so on. It's quite possible to build complicated
data structures using the three basic types in Perl.
Variables in Perl programs can even have two types of values,
depending on how they are interpreted. For instance, $i
can be an integer when used in a numeric operation, and $i
is a string when used in a string operation. Another example is
the $!, which is the errno
code when used as a number but a string when used within a print
statement.
Because variables internal to Perl source code can have many types
of values and definitions, the name must be descriptive enough
to indicate what type it is. By convention, there are three tokens
in Perl source code variable names: arrays, hashes, and scalar
variables. A scalar variable can be further qualified to define
the type of value it holds. The list of token prefixes for these
Perl types are shown in the following list:
AV
|
Array variables
|
HV
|
Hash variables
|
SV
|
Generic scalar variables
|
I32
|
32-bit integer (scalar)
|
I16
|
16-bit integer (scalar)
|
IV
|
Integer or pointer only (scalar)
|
NV
|
Double only (scalar)
|
PV
|
String pointer only (scalar)
|
If you see SV in a function
or variable name, the function is probably working on a scalar
item. The convention is followed closely in the Perl source code,
and you should be able to glean the type of most variable names
as you scan through the code. Function names in the source code
can begin with sv_ for scalar
variables and related operations, av_
for array variables, and hv_
for hashes.
Let's now cover these variable types and the functions to manipulate
them.
Scalar variables in the Perl source are those with SV
in their names. A scalar variable on a given system is the size
of a pointer or an integer, whichever is larger. Specific types
of scalars exist to specify numbers such as IV
for integer or pointer, NV
for doubles, and so on. The SV
definition is really a typedef
declaration of the sv structure
in the header file called sv.h.
NV, IV,
PV, I32,
and I16 are type-specific
definitions of SV for doubles,
generic pointers, strings, and 32- and 16-bit numbers.
Floating-point numbers and integers in Perl are stored as doubles.
Thus, a variable with NV
will be a double that you can cast in a C program to whatever
type you want.
Four types of routines exist to create an SV
variable. All four return a pointer to a newly created variable.
You call these routines from within an XS
Perl extension file:
- SV *newSViv(IV I);
- SV *newSVnv(double d);
- SV *newSVpv(char * p, int len);
- SV *newSVsv(SV *svp);
The way to read these function declarations is as follows. Take
the newSViv(IV) declaration,
for example. The new portion
of the declaration asks Perl to create a new object. The SV
indicates a scalar variable. The iv
indicates a specific type to create: iv
for integer, nv for double,
pv for a string of a specified
length, and sv for all other
types of scalars.
Three functions exist to get the value stored in an SV.
The type of value returned depends on what type of value was set
at the time of creation:
int SvIV(SV*);
| This function returns an integer value of the SV being pointed to. Cast the return value to a pointer if that is how you intend to use it. A sister macro, SvIVX(SV*), does the same thing as the SvIV function.
|
double SvNV(SV*);
| This function returns a floating-point number. The SvNVX macro does the same thing as the SvNV() function.
|
char *SvPV(SV*, STRLEN len);
| This function returns a pointer to a char. The STRLEN in this function call is really specifying a pointer to the len
variable. The pointer to len is used by the function to return the length of the string in SV. The SvPVX pointer returns the string too, but you
do not have to specify the STRLEN len argument.
|
You can modify the value contained in an already existing SV
by using the following functions:
void sv_setiv(SV* ptr, IV incoming);
| This function sets the value of the SV being pointed to by ptr to the integer value in incoming.
|
void sv_setnv(SV* ptr, double);
| This function sets the value of the SV being pointed to by ptr to the value in incoming.
|
void sv_setsv(SV* dst, SV*src);
| This function sets the value of the SV being pointed to by dst to the value pointed to by src in incoming.
|
Perl does not keep NULL-terminated
strings like C does. In fact, Perl strings can have multiple NULLs
in them. Perl tracks strings by a pointer and the length of the
string. Strings can be modified in one of these ways:
void sv_setpvn(SV* ptr, char* anyt ,
int len);
This sets the value of the SV
being pointed to by ptr to
the value in anyt. The string
anyt contains an array of
char items and does not have
to be a NULL-terminated string.
In fact, the string anyt
can contain NULLs because
the function uses the value in len
to keep the string in memory.
void sv_setpv(SV* ptr, char* nullt);
This sets the value of the SV
being pointed to by ptr to
the value in nullt. The nullt
string is a NULL-terminated
string like those in C, and the function calculates and sets the
length for you automatically.
SvGROW(SV* ptr, STRLEN newlen);
This function increases the size of a string to the
size in newlen. You cannot
decrease the size of a string using this function. Make a new
variable and copy into it. You can use the function SvCUR(SV*)
to get the length of a string and SvCUR_set(SV*,
I32 length) to set the length of a string.
void sv_catpv(SV* ptr, char*);
This function appends a NULL-terminated
string to a string in SV.
void sv_catpvn(SV* ptr, char*, int);
This function appends a string of length len
to the SV pointed at by ptr.
void sv_catsv(SV*dst, SV*src);
This appends another SV* to an SV.
Your C program using these programs will crash if you are not
careful enough to check whether these variables exist. To check
whether a scalar variable exists, you can call these functions:
SvPOK(SV*ptr)
| For string |
SvIOK(SV*ptr)
| For integer |
SvNOK(SV*ptr)
| For double |
SvTRUE(SV *ptr)
| For Boolean value |
A value of FALSE received
from these functions means that the variable does not exist. You
can only get two returned values, either TRUE
or FALSE, from the functions
that check whether a variable is a string, integer, or double.
The SvTRUE(SV*) macro returns
0 if the value pointed at
by SV is an integer zero
or if SV does not exist.
Two other global variables, sv_yes
and sv_no, can be used instead
of TRUE and FALSE,
respectively.
Note |
The Perl scalar undef value is stored in an SV instance called sv_undef. The sv_undef value is not (SV *) 0 as you would expect in most versions of C.
|
You can get a pointer to an existing scalar by specifying its
variable name in the call to the function:
SV* perl_get_sv("myScalar",
FALSE);
The FALSE parameter requests
the function to return sv_undef
if the variable does not exist. If you specify a TRUE
value as the second parameter, a new scalar variable is created
for you and assigned the name myScalar
in the current name space.
In fact, you can use package names in the variable name. For example,
the following call creates a variable called desk
in the VRML package:
SV *desk;
desk = perl_get_sv("VRML::desk", FALSE);
Now let's look at collections of scalars: arrays.
The functions for handling array variables are similar in operation
to those for scalar variables. To create an array called myarray,
you would use this call:
AV *myarray = (AV* ) newAV();
To get the array by specifying the name, you can also use the
following function. This perl_get_av()
returns NULL if the variable
does not exist:
AV* perl_get_av(char *myarray,
bool makeIt);
The makeIt variable can be
set to TRUE if you want the
array created, and FALSE
if you are merely checking for its existence and do not want the
array created if it does not exist.
To initialize an array at the time of creation, you can use the
av_make() function. Here's
the syntax for the av_make()
function:
AV *myarray = (AV *)av_make(I32
num, SV **data);
The num parameter is the
size of the AV array, and
data is a pointer to an array
of pointers to scalars to add to this new array called myarray.
Do you see how the call uses pointers to SV,
rather than SVs? The added
level of indirection permits Perl to store any type of SV
in an array. So, you can store strings, integers, and doubles
all in one array in Perl. The array passed into the av_make()
function is copied into a new memory area; therefore, the original
data array does not have
to persist.
Check the av.c source file
in your Perl distribution for more details on the functions and
their parameters. Here is a quick list of the functions you would
most likely perform on AVs.
void av_push(AV *ptr, SV *item);
Pushes an item to the back of an array.
SV* av_pop(AV *ptr);
Pops an item off the back of an array.
SV* av_shift(AV *ptr);
Removes an item from the front of the array.
void av_unshift(AV *ptr, I32 num);
Inserts num items
into the front of the array. The operation in this function only
creates space for you. You still have to call the av_store()
function (defined below) to assign values to the newly added items.
I32 av_len(AV *ptr);
Returns the highest index in array.
SV** av_fetch(AV *ptr, I32 offset, I32
lval);
Gets the value in the array at the offset. If lval
is a nonzero value, the value at the offset is replaced with the
value of lval.
SV** av_store(AV *ptr, I32 key, SV* item);
Stores the value of the item at the offset.
void av_clear(AV *ptr);
Sets all items to zero but does not destroy the array
in *ptr.
void av_undef(AV *ptr);
Removes the array and all its items.
void av_extend(AV *ptr, I32 size);
Resizes the array to the maximum of the current size
or the passed size.
Hash variables have HV in
their names and are created in a manner similar to creating array
functions. To create an HV
type, you call this function:
HV* newHV();
Here's how to use an existing hash function and refer to it by
name:
HV* perl_get_hv("myHash",
FALSE);
The function returns NULL
if the variable does not exist. If the hash does not already exist
and you want Perl to create the variable for you, use:
HV* perl_get_hv("myHash",
TRUE);
As with the AV type, you
can perform the following functions on an HV
type of variable:
- SV** hv_store(HV* hptr,
- char* key The
key of the hash item
- U32 klen, The
length of the key
- SV* val, The
scalar to insert
- U32 hash) Zero
unless you compute the hash function yourself
- SV** hv_fetch(HV* hptr,
- char* keyq The key of
the hash
- U32 klen The
length of the key
- I32 lval) Its
value
Check the file hv.c in your
Perl distribution for the function source file for details about
how the hash function is defined. Both of the previous functions
return pointers to pointers. The return value from either function
will be NULL.
The following functions are defined in the source file:
bool hv_exists(HV*, char* key, U32 klen);
This function returns TRUE or FALSE.
SV* hv_delete(HV*, char* key, U32 klen,
I32 flags);
This function deletes the item, if it exists, at the
specified key.
void hv_clear(HV*);
This function leaves the hash but removes all its
items.
void hv_undef(HV*);
This function removes the hash and its items.
You can iterate through the hash table using indexes and pointers
to hash table entries using the HE
pointer type. To iterate through the array (such as with the each
command in Perl), you can use hv_iterinit(HV*)
to set the starting point and then get the next item as an HE
pointer from a call to the hv_iternext(HV*)
function. To get the item being traversed, make a call to this
function:
SV* hv_iterval(HV*
hashptr, HE* entry);
The next SV is available
via a call to this function:
SV* hv_iternextsv(HV*hptr,
char** key, I32* retlen);
The key and retlen
arguments are return values for the key and its length. See line
600 in the hv.c.
Values in Perl exist until explicitly freed. They are freed by
the Perl garbage collector when the reference count to them is
zero, by a call to the undef
function, or if they were declared local
or my and the scope no longer
exists. In all other cases, variables declared in one scope persist
even after execution has left the code block in which they were
declared. For example, declaring and using $a
in a function keeps $a in
the main program even after returning from the subroutine. This
is why it's necessary to create local variables in subroutines
using the my keyword so that
the Perl interpreter will automatically destroy these variables,
which will no longer be used after the subroutine returns.
References to variables in Perl can also be modified using the
following functions:
int SvREFCNT(SV* sv);
This function returns the current reference count
to an existing SV.
void SvREFCNT_inc(SV* sv);
This function increments the current reference count.
void SvREFCNT_dec(SV* sv);
This function decrements the current reference count.
You can make the reference count be zero to delete the SV
being pointed to and let the garbage handler get rid
of it.
Because the values declared within code blocks persist for a long
time, they are referred to as immortal. Sometimes declaring
and creating variable names in code blocks have the side effect
of persisting even if you do not want them to. When writing code
that declares and creates such variables, it's a good idea to
create variables that you do not want to persist as mortal;
that is, they die when code leaves the current scope.
The functions that create a mortal variable are as follows:
SV* sv_newmortal();
| This function creates a new mortal variable and returns a pointer to it.
|
SV* sv_2mortal(SV*);
| This function converts an existing immortal SV into a mortal variable. Be careful not to convert an already mortal SV into a mortal SV because this operation may result in the reference count for the variable to be decremented twice, leading to unpredictable results.
|
SV* sv_mortalcopy(SV*);
| This function copies an existing SV (without regard to the mortality of the passed SV) into a new mortal SV.
|
To create AV and HV
types, you have to cast the input parameters to and from these
three functions as AV* and
HV*.
Perl subroutines use the stack to get and return values to the
callers. Chapter 27, "Writing Extensions
in C," covers how the stack is manipulated. This section
describes the functions available for you to manipulate the stack.
Note |
Look in the XSUB.h file for more details than this chapter can give you. The details in the header include macro definitions for manipulating the stack in an extension module.
|
Arguments on a stack to a Perl function are available via the
ST(n) macro set. The topmost
item on the stack is ST(0),
and the mth one is ST(m-1).
You may assign the return value to a static value, like this:
SV *arg1 = ST(1); // Assign argument[1]
to arg1;
You can even increase the size of the argument stack in a function.
(This is necessary if you are returning a list from a function
call, for example. I cover this in more detail in Chapter 27.)
To increase the length of the stack, make a call to the macro:
EXTEND(sp, num);
sp is the stack pointer and
num is an extra number of
elements to add to the stack. You cannot decrease the size of
the stack.
To add items to the stack, you have to specify the type of variable
you're adding. Four functions are available for four of the most
generic types to push:
- PUSHi(IV)
- PUSHn(double)
- PUSHp(char*, I32)
- PUSHs(SV*)
If you want the stack to be adjusted automatically, make the calls
to these macros:
- XPUSHi(IV)
- XPUSHn(double)
- XPUSHp(char*, I32)
- XPUSHs(SV*)
These macros are a bit slower but simpler to use.
In Chapter 27, you'll see how to use stacks
in the section titled "The typemap
File." Basically, a typemap
file is used by the extensions compiler xsubpp
for the rules to convert from Perl's internal data types (hash,
array, and so on) to C's
data types (int, char
*, and so on). These rules are stored in the typemap
file in your Perl distribution's ./lib/ExtUtils
directory.
The definitions of the structures in the typemap
file are specified in the internal format for Perl.
As you go through the online docs and the source for Perl, you'll
often see the word magic. The mysterious connotations of
this word are further enhanced by the almost complete lack of
documentation on what magic really is. In order to understand
the phrases "then magic is applied to whatever" or "automagically
[sic]" in the Perl documentation, you have to know what "magic"
in Perl really means. Perhaps after reading this section, you
will have a better feel for Perl internal structures and actions
of the Perl interpreter.
Basically, a scalar value in Perl can have special features for
it to become "magical." When you apply magic to a variable,
that variable is placed into a linked list for methods. A method
is called for each type of magic assigned to that variable when
a certain action takes place, such as retrieving or storing the
contents of the variable. Please refer to a comparable scheme
in Perl when using the tie()
function as described in Chapter 6, "Binding
Variables to Objects." When tie-ing a variable to
an action, you are defining actions to take when a scalar is accessed
or when an array item is read from. In the case of magic actions
of a scalar, you have a set of magic methods that are called when
the Perl interpreter takes a similar action on (like getting a
value from or putting a value into) a scalar variable.
To check whether a variable has magic methods associated with
it, you can get the flags for it using the SvFLAGS(sv)
macro. The (sv) here is the
name of the variable. The SvMAGIC(variable)
macro returns the list of methods that are magically applied to
the variable. The SvTYPE()
of the variable is SVt_PVMG
if it has a list of methods. A normal SV
type is upgraded to a magical status by Perl if a method is requested
for it.
The structure to maintain the list is found in the file mg.h
in the Perl source files:
struct magic {
MAGIC* mg_moremagic;
//
pointer to next method. NULL if none.
MGVTBL* mg_virtual;
// pointer
to table of methods.
U16 mg_private; //
internal variable
char mg_type; //
type of methods
U8 mg_flags; //
flags for this method
SV* mg_obj; //
Reference to itself
char* mg_ptr; //
name of the magic variable
I32 mg_len; //
length of the name
};
The mg_type value sets up
how the magic function is applied. The following items are used
in the magic table. You can see the values in use in the sv.c
file at about line 1950. Table 25.2, which has been constructed
from the switch statement,
tells you how methods have to be applied.
Table 25.2. Types of Magic functions in mg_type.
Mg_type
| Virtual Magic Table | Action Calling Method
|
\0
| vtbl_sv
| Null operation |
A
| vtbl_amagic
| Operator overloading |
a
| vtbl_amagicelem
| Operator overloading |
c
| 0 |
Used in operator overloading |
B
| vtbl_bm
| Unknown |
E
| vtbl_env
| %ENV hash
|
e
| vtbl_envelem
| %ENV hash element
|
g
| vtbl_mglob
| Regexp applied globally
|
I
| vtbl_isa
| @ISA array
|
i
| vtbl_isaelem
| @ISA array element
|
L
| 0 |
Unknown |
l
| tbl_dbline
| n line debugger
|
P
| tbl_pack
| Tied array or hash |
p
| vtbl_packelem
| Tied array or hash element |
q
| vtbl_packelem
| Tied scalar or handle |
S
| vtbl_sig
| Signal hash |
s
| vtbl_sigelem
| Signal hash element |
t
| vtbl_taint
| Modified tainted variable |
U
| vtbl_uvar
| Unknown variable type |
v
| vtbl_vec
| Vector |
x
| vtbl_substr
| Substring |
*
| vtbl_glob
| The GV type
|
#
| vtbl_arylen
| Array length |
.
| vtbl_pos
| $. scalar variable
|
The magic virtual tables are defined in embed.h.
The mg_virtual field in each
magic entry is assigned to the address of the virtual table.
Each entry in the magic virtual table has five items, each of
which is defined in the following structure in the file mg.h:
struct mgvtbl {
int (*svt_get) _((SV
*sv, MAGIC* mg));
int (*svt_set) _((SV
*sv, MAGIC* mg));
U32 (*svt_len) _((SV
*sv, MAGIC* mg));
int (*svt_clear) _((SV
*sv, MAGIC* mg));
int (*svt_free) _((SV
*sv, MAGIC* mg));
};
The svt_get() function is
called when the data in SV
is retrieved. The svt_set()
function is called when the data in SV
is stored. The svt_len()
function is called when the length of the string is changed. The
svt_clear() function is called
when SV is cleared, and the
svt_free() function is called
when SV is destroyed.
All tables shown in the perl.h
file are assigned mgvtbl
structures. The values in each mgvtbl
structure for each item in a table define a function to call when
an action that affects entries in this table is taken by the Perl
interpreter. Here is an excerpt from the file:
EXT MGVTBL vtbl_sv =
{magic_get, magic_set, magic_len,0,0};
EXT MGVTBL vtbl_env =
{0, 0, 0, 0, 0};
EXT MGVTBL vtbl_envelem =
{0, magic_setenv, 0,magic_clearenv,
0};
EXT MGVTBL vtbl_sig =
{0, 0, 0, 0, 0};
EXT MGVTBL vtbl_sigelem =
{0, magic_setsig, 0,0,
0};
The vbtl_sv is set to call
three methods: magic_get(),
magic_set(), and magic_len()
for the magic entries in sv.
The zeros for vtbl_sig indicate
that no magic methods are called.
If you are still awake, you'll notice a reference to GV
in the source file. GV stands
for global variable, and the value stored in GV
is any data type from scalar to a subroutine reference. GV
entries are stored in a hash table, and the keys to each entry
are the names of the symbols being stored. A hash table with GV
entries is also referred to as a stash. Internally, a GV
type is the same as an HV
type.
Keys in a stash are also package names, with the data item pointing
to other GV tables containing
the symbol within the package.
Most of the information in this chapter has been gleaned from
source files or the online documents on the Internet. There is
a somewhat old file called perlguts.html
by Jeff Okamoto (e-mail okamoto@corp.hp.com)
in the www.metronet.com archives
that has the Perl API functions and information about the internals.
Note that the perlguts.html
file was dated 1/27/1995, so it's probably not as up-to-date as
you would like.
Please refer to the perlguts.html
or the perlguts man page
for a comprehensive listing of the Perl API. If you want a listing
of the functions in the Perl source code and the search strings,
use the ctags *.c command
on all the .c files in the
Perl source directory. The result will be a very long file (800
lines), called tags, in the
same directory. A header of this file is shown here:
ELSIF perly.c /^"else
: ELSIF '(' expr ')' block else",$/
GvAVn gv.c /^AV *GvAVn(gv)$/
GvHVn gv.c /^HV *GvHVn(gv)$/
Gv_AMupdate gv.c /^Gv_AMupdate(stash)$/
HTOV util.c /^HTOV(htovs,short)$/
PP pp.c /^PP(pp_abs)$/
PP pp.c /^PP(pp_anoncode)$/
PP pp.c /^PP(pp_anonhash)$/
PP pp.c /^PP(pp_anonlist)$/
PP pp.c /^PP(pp_aslice)$/
If you are a vi hack, you
can type :tag functionName
to go to the line and file immediately from within a vi
session. Ah, the old vi editor
still has a useful function in this day and age. emacs
users can issue the command etags *.c
and get a comparable tags
file for use with the M-x find-tag
command in emacs.
This chapter is a reference-only chapter to prepare you for what
lies ahead in the rest of the book. You'll probably be referring
to this chapter quite a bit as you write include
extensions.
There are three basic types of variables in Perl: SV
for scalar, AV for arrays,
and HV for hash values. Macros
exist for getting data from one type to another. You'll need to
know about these internal data types if you're going to be writing
Perl extensions, dealing with platform-dependent issues, or (ugh)
embedding C code in Perl and vice versa. The dry information in
this chapter will serve you well in the rest of this book.
Chapter 26
Writing C Extensions in Perl
CONTENTS
This chapter introduces a way to embed the Perl interpreter into
a C program. After reading this chapter, you should be able to
integrate the Perl interpreter or its library code with a C application.
The information in this chapter relies heavily on the discussion
of Perl's internal data types from Chapter 25,
"Perl Internal Files and Structures."
The Perl interpreter is written in C and can therefore be linked
with C code. The combination process is relatively straightforward.
However, there are some caveats that you should be aware of. I
discuss these caveats in this chapter. Also, even though you can
combine C and Perl code, you might want to rethink the way you
want to use each language. Both C and Perl have their strong points.
C code can be optimized to a greater degree than can Perl code.
Perl is great for processing text files and strings, whereas manipulation
strings in C is a bit clumsy at times.
Several alternatives exist for combining C and Perl code. You
can use extensions, call complete programs, run a background process,
and so on. For example, if you want to create a library of mathematical
functions to use in your Perl programs, you can write an extension
and use it from within your Perl code. If the functionality you
need from a C program can be encapsulated into an executable program,
you can call this program from within a system call. The system
call will force your Perl program to wait until the called program
terminates. You can start the executable program as a background
process from the command line or from within a Perl program using
a fork system call.
If one of these methods will solve your problem, you may not have
to take the more complicated route of embedding Perl in C code.
Think through your design thoroughly before deciding which solution
is best. If you feel that your design requires you to write a
C program and also use the functionality of Perl from within your
program, you are left with no alternative except to follow the
more complicated route.
The first question to answer is Whether the solution you are deriving
is based for the UNIX platform? Most of the tested situations
to date for combining C code with Perl are those on the UNIX platform.
Such a combination is therefore not viable for non-UNIX platforms.
If you intend to port the combined code to an NT system, it simply
won't compile, let alone work. Therefore, if you've concluded
that you must embed the Perl interpreter in your C code, keep
in mind that you're also limiting your solution to UNIX platforms.
Embedding Perl in C code on Windows will not work at the moment,
so you might want to rethink your design to see whether you can
obtain comparable functionality using extension libraries.
The second question to answer is What exactly is the solution
you are trying to achieve by combining Perl with C? Again, if
all you want do is use C code from within Perl, you might want
to consider writing the C code as a Perl extension. In such an
event, you should rethink your design to see how to use only portions
of the C code as parts of an extension library for a Perl program.
The methods to do just this are covered in Chapter 27,
"Writing Extensions in C."
Normally you want to write extensions in C because the compiled
code is faster. For example, complex mathematical calculations
are probably best written in C rather than in Perl. The compiled
C code runs much faster than interpreted code in Perl for specific
tasks. Also, with the use of extensions, it's possible to send
in pointers to variables, existing with the Perl program, into
the extension code. By receiving pointers to the Perl variables,
code within extensions can modify the contents of variables directly.
Of course, if you are attempting to run another complete C program
from Perl, consider using the system(),
backtick, or exec()
calls. They are convenient ways of calling complete programs.
With the open() call using
pipes, it's easy to collect the standard output from the executed
application. However, you are constrained to reading only the
output from the child process you started. The child process cannot
manipulate any Perl variables directly. The Perl code and the
called code run as completely different applications in their
own address spaces. This is in contrast to working with Perl's
extensions that run C as part of the calling process. (Of course,
you can take explicit measures to create a bi-directional pipe
through which to communicate.)
The flexibility in the two methods outlined up to now in this
section solves a majority of the problems solved using C and Perl.
In both methods, though, the calling program is a Perl application.
What if you want to call Perl code from within a C application?
You can write the Perl code as an executable script and then make
a system() call from within
the C code. However, you'll be constrained by the same things
as you were using the system()
call from within Perl. There is no direct connection between the
child process started with system()
and the calling application, unless you take explicit measures
to create a communication channel like a socket or pipe.
Sometimes you just have to call Perl code from within a C program.
For example, the C language is not designed to process regular
expressions. The functionality of parsing tokens from a string
using the strtok() function
may not be sufficient for your problem. There are ways to port
some regular expression parsers like grep
into C. (A good example is Allen Holub's port of grep
in an article in Dr. Dobbs, October, 1984, and in The
Dr. Dobbs Toolbox of C, Brady Books, 1986.) Perhaps all you
need is simple regular expression parsing, in which case using
a port of grep makes sense.
The grep code you link will
not have the overhead of the entire Perl preprocessor.
However, if all else fails and you do want the Perl interpreter
in your C program, or at the very least want to call a Perl subroutine
from within your C program, this chapter might provide the information
you need. Here are the topics I will cover:
- How to add a Perl interpreter to a C program
- How to call a Perl subroutine from within
a C program
- How to use Perl pattern matches and string
substitutions
First of all, make sure you have read access to the Perl 5 distribution
including Perl header files and linking Perl libraries. Make sure
that your Perl 5.002 source code distribution is complete and
installed correctly. Copying the Perl executable program from
another machine won't work because you need the whole source tree
to work with your C program.
Essentially, the files you need are the EXTERN.h
and perl.h header files.
The Perl libraries should exist in a directory using the following
format:
/usr/local/lib/perl5/your_architecture_here/CORE
Execute this statement for a hint about where to find CORE:
perl -e 'use Config; print $Config{archlib}\n'
On my Linux system, this program returned the following pathname
(the path might be completely different for your machine):
/usr/lib/perl5/i486-linux/5.002
The command line to use for compiling and running a program is
gcc -o filename filename.c -L($LIBS)
-I($IncS)
The -L and -I
flags define the locations of the library and header files. The
libraries that you are linking with are
perl -e 'use Config; print $Config{libs}
, "\n";'
An easier way to find out which libraries you are using is to
use the ExtUtils::embed module
extensions. This library is available from any CPAN site and is
in the public domain.
ExtUtils::embed is a set
of utility functions used when embedding a Perl interpreter and
extensions in your C/C++ applications. You do not have to use
this library, but it does a lot of the basic grunt work (such
as finding the correct libraries, include files, and definitions)
for you. The author of the ExtUtils::embed
package is Doug MacEachern (dougm@osf.org).
You can address problems and comments to him directly.
Installing the package is easy. Simply untar
the archive, which will create a directory called ExtUtils-embed-version_number.
Change directory into this new directory and run these commands:
perl Makefile.PL
make
make test
make install
Usually, you'll place a call to the embed.pm
function in a makefile. The instructions on how to do this are
in the embed.pm package itself.
In practice, however, I just took the values returned from a few
calls to the embed.pm functions
and placed them directly in a makefile. This way there was a written
record in the makefile for the explicit pathnames used to build
the programs I happen to be using. The risk was that if the location
of the Perl library changed in the future, my makefile would break.
This change is too unlikely to happen on my machine because I
administer it. Your case might be different if you are on a multiuser
system or are writing this makefile for the benefit of a group.
The one-line command to compile and link the ex1.c
file in a makefile is
$gcc -o ex1 ex1.c 'perl -MExtUtils::embed
-e ccopts -e ldopts'
In fact, this line can be placed in a shell script like this:
$gcc -o $1 $1.c 'perl -MExtUtils::embed
-e ccopts -e ldopts'
Each execution of the makefile will cause the Perl script to recreate
the include and link paths. This might slow down each execution
of make. A make
variable set to a constant value will probably let make
process the makefile faster. I discuss this procedure in a moment.
In any event, the returned values from the call to use the ExtUtils::embed
function are used to define the link libraries and include files.
The returned values can be used directly in makefiles should the
Perl -e command not work
or if you prefer to use a make
variable.
Listing 26.1 presents a sample makefile for the Linux machine.
Listing 26.1. A sample makefile.
1 IncK= -D__USE_BSD_SIGNAL -Dbool=char
-DHAS_BOOL
Â-I/usr/local/include -rdynamic -I
/usr/lib/perl5/i486-linux/5.002/CORE
2 LIBK = -L/usr/local/lib /usr/lib/perl5/i486-linux/5.002
Â/auto/DynaLoader/DynaLoader.a -L/usr/lib/perl5/i486-linux/5.002/CORE
Â-lperl -lgdbm -ldbm -ldb -ldl -lm -lc -lbsd
3 K_LIBS = -lgdbm -ldbm -ldb -ldl -lm -lc -lbsd
4
5 ex2 : ex2.c
6 $(cc) -fno-strict-prototype ex2.c
-o ex2 -L$(LIBK) -I$(IncK)
Note the flags for the gcc
compiler. The main problem with the gcc
compiler is how the "safefree" function prototype is
declared in the proto.h and
handy.h files. There is a
slight difference in the syntax of each declaration, but programmatically
it makes no difference. To turn off the checking in gcc,
simply use the -fno-strict-prototype
flag at the command line for the gcc
command.
The LIBK and IncK
paths are set to values that are derived from running the Perl
program shown in Listing 26.2. There is one possible problem you
must be aware of when you run this program: if you get errors
stating that it cannot find embed.pm
in the @Inc array, then modify
the @Inc array to include
the path where the file is located. The commented lines in Listing
26.2 are examples.
If all else fails, copy the embed.pm
path to the directory you happen to be in. If you get an error
stating that embed.pm could
not be included or that it was empty, you have to modify the embed.pm
file. Go to the statement with the _END_
label and add the line 1;
before it. This step is only necessary if the ExtUtils::embed
file could not be included.
Listing 26.2. A sample makefile.
1 #!/usr/bin/perl
2
3 use ExtUtils::embed;
4
5 #
6 # unshift(@Inc,"/usr/local/lib/perl5/site_perl");
7 #
8
9 &ccopts; # Create the path for headers
10 &ldopts; # Create the path for libraries
The call to the &ccopts
function creates the include path for use with the -I
flag. The call to &ldopts
creates the path for libraries to be linked with the -L
flag. Pipe the output to a saved file and create the makefile
as shown in Listing 26.1.
A C program using a Perl interpreter is really creating and running
a PerlInterpreter object.
The PerlInterpreter object
type is defined in the Perl library, and the C program simply
makes a reference to this library object. Several sample files
come in the embed.pm file
and are used here as examples.
Listing 26.3 presents a quick example of how to embed a Perl interpreter
in a C program.
Listing 26.3. The first example from the embed.pm
module.
1 /*
2 ** Sample program used from embed.pm module package.
3 */
4 #include <stdio.h>
5 #include <EXTERN.h>
6 #include <perl.h>
7
8 static PerlInterpreter *my_perl;
9
10 main(int argc, char **argv, char **env)
11 {
12
13 my_perl
= perl_alloc();
14 perl_construct(my_perl);
15 perl_parse(my_perl,
NULL, argc, argv, env);
16 perl_run(my_perl);
17 perl_destruct(my_perl);
18 perl_free(my_perl);
19 }
Lines 3 to 6 are the include headers you have to use to get this
to work. The EXTERN.h and
perl.h files will be picked
from where the Perl distribution is installed.
At line 8, the C program creates a pointer reference to the PerlInterpreter
object defined in the Perl libraries. The reference will actually
be resolved in line 13 when the object is created.
At line 10, the main program interface
is called. All three arguments are required. Do not use either
of these lines because they both caused compiler error, even with
the -fno-strict-prototypes flag set:
main(int argc, char **argv);
main(int argc, char *argv[], char *env[])
Lines 14 and 15 construct the PerlInterpreter
object and parse any environment variables and command-line arguments.
You can read and execute Perl statements from a file at any time
in a C program by simply placing the name of the file in argv[1]
before calling the perl_run
function. The perl_run function
is called at line 16 in the sample code in Listing 26.2. The function
can be called repeatedly in the C code before the calls are made
to destruct and free the object (lines 17 and 18 in the sample
code).
Now make this program, called
ex2.c, and run it. In the
sample run that follows, note how variables are defined and used
interactively in this sample run:
$ ex2
$a = 1;
$b = 3;
print $a," ",$b," ",$a+$b,"\n";
^D
1 3 4
$
To run a script file, simply redirect the contents of a file into
the input of the interpreter. The file you are feeding into your
C mini-interpreter does not have to have its execute bit set in
its permissions. Here's a sample run.
$ cat test.pl
$a = 1;
$b = 1;
print "a + b = ", $a + $b, "\n";
$
$ ex2 < test.pl
a + b = 2
$
There you have it-a small Perl interpreter embedded in C code.
Once you have this interpreter embedded in your C code, you can
evaluate Perl statements by simply feeding them into the interpreter
one line at a time.
There will be occasions, though, when you simply want to call
a Perl subroutine directly from within the C code. I show you
how to do this in the next section.
In order to call a Perl subroutine by name, simply replace the
call to perl_run() with a
call to perl_call_argv().
An example is shown in the code in Listing 26.4.
Listing 26.4. Calling a subroutine in Perl directly.
1 #include <stdio.h>
2 #include <EXTERN.h>
3 #include <perl.h>
4
5 static PerlInterpreter *my_perl;
6
7 int main(int argc, char **argv,
char **env)
8 {
9 my_perl
= perl_alloc();
10 perl_construct(my_perl);
11
12 perl_parse(my_perl,
NULL, argc, argv, env);
13 /* The next line calls a function in the file named
in
14 * argv[1] of the program !!*/
15 perl_call_argv("showUser",
G_DISCARD | G_NOARGS, argv);
16 perl_destruct(my_perl);
17 perl_free(my_perl);
18 }
Look closely at line 15. This is really the only line that is
different from the code shown in Listing 26.3. A Perl subroutine
called showUser is being
called here. The showUser
subroutine takes no arguments, so you specify a G_NOARGS
flag, and returns no values, so specify the G_DISCARD
flag. The argv vector is
used to store the filename in argv[1].
To invoke this program, type the name of the file (showMe.pl,
in this case) at the command line:
$ ex3 showMe.pl
Process 2689 : UID is 501 and GID is 501
The showMe.pl file named
in argv[1] is shown in Listing
26.5.
Listing 26.5. The file containing the subroutine being called.
1 #!/usr/bin/perl
2 sub showUser {
3 print "Process $$ : UID is
$< and GID is $(\n";
4 }
Calling Perl functions with arguments and using the return values
requires manipulation of the Perl stack. When you make the call,
you push values onto the stack, and upon return from the function
you get the returned value off the stack. Let's see how to work
with the calling stack.
Note |
A note to the Perl-savvy reader: You can get the values from Perl special variables directly. See the section titled "Getting Special Variable Values," later in this chapter.
|
Here is another Perl subroutine, which prints whatever parameters
are passed to it:
sub PrintParameters
{
my(@args) = @_
;
for $i (@args)
{ print "$i\n" }
}
Here is the function to use when calling this Perl subroutine:
static char *words[] = {"My",
"karma", "over", "my", "dogma",
NULL} ;
static void justDoit()
{
dSP;
perl_call_argv("PrintParameters",
G_DISCARD, words) ;
}
As you can see, it's easy to construct parameters and then use
them directly in C statements to call Perl functions or programs.
Perl has several C functions to use when calling Perl subroutines.
Here are the most important ones to know:
- perl_call_sv
- perl_call_pv
- perl_call_method
- perl_call_argv
The perl_call_sv function
is called by the other three functions in the list. These three
functions simply fiddle with their arguments before calling the
perl_call_sv function. All
these functions take a flags parameter to pass options. We'll
discuss the meaning of these flags shortly.
All these functions return an integer of type I32.
The value returned is the number of items on the Perl stack after
the call returns. It's a good idea to check this value when using
unknown code. Calling functions use the return value to determine
how many returned values to pick up from the stack after the calling
function returns.
Note |
One important point to note here is that you'll see a lot of types of returned values and arguments passed into functions. These declarations come from the Perl sources and header files starting from perl.h. You really
do not need to know how I32 is defined, but its name suggests it's a 32-bit integer. If you are really curious to see how it works or what the definitions are, check out the perl.h
header file. Please refer to Chapter 25 for more information on internal Perl variables.
|
The syntax for this function is
I32 perl_call_sv(SV* sv, I32 flags) ;
The perl_call_sv takes two
arguments. The first argument, sv,
is a pointer to an SV structure.
(The SV structure is also
defined in the header file perl.h.)
The SV stands for scalar
vector. This way you can specify the subroutine to call either
as a C string by name or by a reference to a subroutine.
The function perl_call_pv
is like the perl_call_sv
call except that it expects its first parameter to be a string
containing the name of the subroutine to call. The syntax to this
function is
I32 perl_call_pv(char *subname, I32 flags)
;
For example, to specify the name of function, you would make a
call like this:
perl_call_pv("showUser",0);
The function name can be qualified to use a package name. To explicitly
call a routine in a package, simply prepend the name with a PackageName::
string. For example, to call the function Time
in the Datum package, you
would make this call:
perl_call_pv("Datum::Time",0);
This function is used to call a method from a Perl class. The
syntax for this call is
I32 perl_call_method(char *methodName,
I32 flags) ;
methodName is set to the
name of the method to be called. The class in which the called
method is defined is passed on the stack and not in the argument
list. The class can be specified either by name or by reference
to an object.
This subroutine calls the subroutine specified in the subname
parameter. The values of the flags that are passed in when making
this function call will be discussed shortly. The argv
pointer is set in the same manner as the ARGV
array to a Perl program: each item in the argv
array is a pointer to NULL-terminated
strings. The syntax for this call is
I32 perl_call_argv(char *subname, I32
flags, register char **argv) ;
The flags parameter in all
the functions discussed in the previous section is a bitmask that
can consist of the following values:
- G_DISCARD
- G_NOARGS
- G_SCALAR
- G_ARRAY
- G_EVAL
The following sections detail how each flag affects the behavior
of the called function.
The G_DISCARD flag is used
to specify whether a function returns a value or not. If the G_DISCARD
flag is set to True, no values
are returned. By default, a returned value or a set of values
from the perl_call functions
are placed on the stack, and placing these values on the stack
does take time and processing. If you are not interested in these
values, set the G_DISCARD
flag to get rid of these items. If this flag is not specified,
there might be returned values pushed onto the stack that you
might not be aware of unless you explicitly check the returned
value of the function call. Therefore, specify the flag explicitly
if you don't care to even look for returned values.
Normally you'll be passing arguments into a Perl subroutine. The
default procedure is to create the @_
array for the subroutine to work with. If you are not passing
any parameters to the Perl subroutine, you can save processing
cycles by not creating the @_
array. Setting the flag stops the flag from being created.
Be sure that the function you are calling does not use arguments.
If the called Perl subroutine does use parameters and you do not
pass any parameters, your program might return totally bogus results.
In such cases, the last value of @_
is used.
The flag specifies that only one scalar value will be expected
back from this function. The called subroutine might attempt to
return a list, in which case only the last item in the list will
be returned. Setting this flag sets the context under which the
called subroutine will run. G_SCALAR
is the default context if no context is specified.
When this flag is specified, the returned value from the called
function will either be 0
or 1: 0
is returned if the G_DISCARD
flag is set; otherwise, 1
is returned. If a 1 is returned,
you must remove the returned value to restore the stack back to
what it was before the call was made.
Tip |
The called subroutine can call the wantarray function to determine if it was called in scalar or array context. If the call returns false, the called function is called in scalar
context. If the call returns true, the called function is called in array context.
|
Set this flag when you want to return a list from the called Perl
subroutine. This flag causes the Perl subroutine to be called
in a list context. 0 is returned
when the G_DISCARD flag is
specified along with this flag. If the G_DISCARD
flag is not specified, the number of items on the stack is returned.
This number is usually the number of items the calling routine
pushed on the stack when making the function call; however, the
number of items could be different if the called subroutine has
somehow manipulated the stack internally. If G_ARRAY
was specified and the returned value is 0,
an error has occurred in the called routine.
The called subroutine might crash while processing bogus input
parameters. It's possible to trap an abnormal termination by specifying
the G_EVAL statement. The
net effect of this flag is to put the called subroutine in an
evaluated block from which it's possible to trap all but the more
shameful errors. Whenever control returns from the function, you
have to check the contents of the $@
variable for any possible error messages. Remember that any anomaly
can set the contents of $@,
so check the value as soon as you return from a subroutine call.
The value returned from the perl_call_*
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: If an error occurs when a G_SCALAR
is specified, the value on top of the stack will be undef.
The value of $@ will also
be set. Just remember to pop the undef
from the stack.
Here is an example of how to call a Perl function that takes three
arguments and returns an integer. This is an example of using
a function in a scalar context because it returns a scalar value.
The code is shown in Listing 26.6.
Listing 26.6. A function used in a scalar context.
1 /* How to call a Perl subroutine
from C */
2 #include <stdio.h>
3 #include <EXTERN.h>
4 #include <perl.h>
5
6 static int getSeconds(int
s, int m, int h);
7 static PerlInterpreter *my_perl;
8
9 int main(int argc, char **argv,
char **env)
10 {
11 my_perl
= perl_alloc();
12 perl_construct(my_perl);
13
14 perl_parse(my_perl,
NULL, argc, argv, env);
15 getSeconds(10,30,4);
/* TIME = 10:30:04 AM */
16 perl_destruct(my_perl);
17 perl_free(my_perl);
18 }
19
20 static int getSeconds(int s, int
m, int h)
21 {
22 dSP ; /*
init stack pointer */
23 int count
; /* keep return value */
24 ENTER
; /* start
temporary area */
25 SAVETMPS;
26 PUSHMARK(sp)
; /* push mark
for last argument. */
27 XPUSHs(sv_2mortal(newSViv(s)));
/* leftmost argument */
28 XPUSHs(sv_2mortal(newSViv(m)));
/* go from left to right */
29 XPUSHs(sv_2mortal(newSViv(h)));
/* rightmost argument */
30 PUTBACK
; /*
make stack pointer available */
31 count
= perl_call_pv("seconds", G_SCALAR); /* call */
32 SPAGAIN
; /* reset stack pointer
*/
33 if (count
!= 1) /* check return value */
34 croak("Whoa
Nelly! This is wrong\n") ;
35 printf
("The number of seconds so far = %f for %d:%d:%d\n",
POPi,h,m,s) ;
36 PUTBACK
; /* put the popped value on stack again */
37 FREETMPS
; /* free up temporary variables (NOT count) */
38 LEAVE
; /* get out and clean up stack */
39 }
Lines 2 through 4 declare the mandatory headers. At line 7 we
declare the prototype for the function we are going to call. You
can declare the function here instead if you like. The call to
this function, getSeconds,
is made at line 15. The function itself is declared static to
prevent unlikely confusion with any predefined functions in the
Perl libraries.
At line 22, the call to the dSP
macro initializes the stack. At line 23, the count
variable is declared to be a nontemporary variable on the stack.
The ENTER and SAVETMPS
macros at lines 24 and 25 start the temporary variable area. A
marker to this stack location is pushed on at line 26.
The ENTER/SAVETMPS pair creates
the start of code for all temporary variables that will be destroyed
on the return from the C function. The FREETMPS/LEAVE
pair will be used to clean up and destroy the space allocated
on the calling stack for these temporary variables.
Now the parameters to the Perl subroutine are pushed onto the
stack one at a time from the leftmost parameter to the rightmost
parameter. Remember this order because the Perl function expecting
these parameters will be declared as this:
sub seconds {
my($h, $m, $s)
= @_ ;
my $t;
$t = $s + $m * 60 + $h * 3600;
return
$t
}
The stack pointer is made into a globally available value with
the PUTBACK macro in line
30. The actual call to the subroutine is made in line 31 with
the G_SCALAR flag. On return
from the subroutine, we have to reset the stack pointer with the
SPAGAIN (stack pointer again)
macro. The count must be 1,
or else we have an error.
The returned value is in POPi.
The called function returned an integer value. To get other types
of values, you can use one of the following macros:
- POPs for an SV
- POPp for a pointer (such
as a pointer to a string)
- POPn for a double
- POPi for an integer
- POPl for a long
The PUTBACK macro is used
to reset the Perl stack back to a consistent state just before
exiting the function. The POPi
macro call only updated the local copy of the stack pointer. We
have to set the global value on the stack, too. All parameters
pushed onto the stack must be bracketed by the PUSHMARK
and PUTBACK macros. These
macros count the number of parameters being pushed and hence let
Perl know how to size the @_
array. The PUSHMARK macro
tells Perl to mark the stack pointer and must be specified even
if you are using no parameters. The PUTBACK
macro sets the global copy of the stack pointer to the value of
the local copy of the stack pointer.
Here's another example of how to use a returned string from a
function using the POPp macro.
(See Listing 26.7.) Look at lines 23 through 25 to see how strings
and integers are pushed onto the stack with the XPUSHs(sv_2mortal(newSVpv(str,offset)));
and XPUSHs(sv_2mortal(newSViv(offset)));
functions. The returned value from the actual call to the Perl
function is retrieved with the POPp
macro.
Listing 26.7. Using a returned string value.
1 /* Using returned strings from
functions */
2 #include <stdio.h>
3 #include <EXTERN.h>
4 #include <perl.h>
5
6 static int MySubString(char
*a, int offset, int len);
7 static PerlInterpreter *my_perl;
8
9 int main(int argc, char **argv,
char **env)
10 {
11 my_perl
= perl_alloc();
12 perl_construct(my_perl);
13 perl_parse(my_perl,
NULL, argc, argv, env);
14 MySubString("Kamran
Was Here",7,3); /* return 'Was' */
15 perl_destruct(my_perl);
16 perl_free(my_perl);
17 }
18
19 static int MySubString(char *a,
int offset, int len)
20 {
21 dSP ;
22 PUSHMARK(sp)
;
23 XPUSHs(sv_2mortal(newSVpv(a,
0)));
24 XPUSHs(sv_2mortal(newSViv(offset)));
25 XPUSHs(sv_2mortal(newSViv(len)));
26 PUTBACK
;
27 perl_call_pv("Csubstr",
G_SCALAR);
28 SPAGAIN
;
29 printf
("The substring is %s\n",(char *)POPp) ;
30 PUTBACK
;
31 FREETMPS
;
32 LEAVE
;
33 }
The function Csubstr calls
the Perl substr() as shown
here:
sub Csubstr {
my ($s,$o,$l) = @_;
return substr($s,$o,$l);
}
The value of the substr()
function call is returned back from the subroutine call. It's
this returned value that is used in the C program.
Many Perl functions return lists as their results. C programs
can retrieve these values as well. Here's a simple Perl function
that returns the ratio of two numbers. (See Listing 26.8.) The
C program to call this function is shown in Listing 26.9.
Listing 26.8. Ratio of numbers in a Perl function.
1 sub GetRatio
2 {
3 my($a, $b) = @_ ;
4 my $c, $d;
5 if ($a == 0) { $c = 1; $d = 0; }
6 elsif ($b == 0) { $c = 0; $d = 1; }
7 else {
8 $c = $a/$b;
9 $d = $b/$a;
10 }
11 ($c,$d);
12 }
Look at lines 34 and 35 in Listing 26.9. The returned values from
the Perl function are picked off one at a time using the POPn
macro to get double values from the stack. The global stack is
readjusted before returning from the C function.
Listing 26.9. Calling the GetRatio
function.
1 /* How
to return lists back from Perl functions */
2
3 #include <stdio.h>
4 #include <EXTERN.h>
5 #include <perl.h>
6
7 static void getRatio(int
a, int b);
8 static PerlInterpreter *my_perl;
9
10 int main(int argc, char **argv,
char **env)
11 {
12 my_perl
= perl_alloc();
13 perl_construct(my_perl);
14 perl_parse(my_perl,
NULL, argc, argv, env);
15 getRatio(8,3);
16 perl_destruct(my_perl);
17 perl_free(my_perl);
18 }
19
20
21 static void getRatio(int a, int
b)
22 {
23 dSP ;
24 int count
;
25 ENTER
;
26 SAVETMPS;
27 PUSHMARK(sp)
;
28 XPUSHs(sv_2mortal(newSViv(a)));
29 XPUSHs(sv_2mortal(newSViv(b)));
30 PUTBACK
;
31 count
= perl_call_pv("GetRatio", G_ARRAY);
32 SPAGAIN
;
33 if (count
!= 2) croak("Whoa! \n") ;
34 printf
("%d / %d = %f\n", a, b, POPn) ;
35 printf
("%d / %d = %f\n", b, a, POPn) ;
36 PUTBACK
;
37 FREETMPS
;
38 LEAVE
;
39 }
Placing G_SCALAR instead
of G_ARRAY in the code in
Listing 29.9 would have forced a scalar value to be returned.
Only the last item of the array would have been returned and the
value of count would be set
to 1.
Note how this Perl subroutine takes precautions not to crash by
first checking the divisor by zero. Now, this time let's not return
a value. Instead, let's call the die()
function if a bogus value is sent into the function GetRatio.
We'll try to trap the errors caused by calling the function with
the G_EVAL flag set.
The G_EVAL flag is useful
when calling functions you think may die().
The G_EVAL flag is OR-ed
in with any other flags to such a call. Listing 26.10 presents
a Perl function that calls the die
function in case one of the arguments sent into it is zero. Because
we know that this function can die,
we'll send in a value that causes it to die.
The code to make this fatal call (to illustrate how G_EVAL
is used) is shown in Listing 26.11.
Listing 26.10. A Perl function that can die.
1 sub GetRatioEval
2 {
3 my($a,
$b) = @_ ;
4 my $c, $d;
5 die "Hey! A is 0 \n"
if ($a == 0);
6 die "Hey! B is 0 \n"
if ($b == 0);
7 $c = $a/$b;
8 $d = $b/$a;
9 ($c,$d);
10 }
Listing 26.11. A C program to use the G_EVAL
flag.
1 /* Call the suicidal
function to use G_EVAL */
2
3 #include <stdio.h>
4 #include <EXTERN.h>
5 #include <perl.h>
6
7 static void getRatio(int
a, int b);
8 static PerlInterpreter *my_perl;
9
10 int main(int argc, char **argv,
char **env)
11 {
12 my_perl
= perl_alloc();
13 perl_construct(my_perl);
14 perl_parse(my_perl,
NULL, argc, argv, env);
15 getRatio(8,0);
16 perl_destruct(my_perl);
17 perl_free(my_perl);
18 }
19
20
21 static void getRatio(int a, int
b)
22 {
23 dSP ;
24 int count
;
25 SV
*svp; /*
New line */
26 ENTER
;
27 SAVETMPS;
28 PUSHMARK(sp)
;
29 XPUSHs(sv_2mortal(newSViv(a)));
30 XPUSHs(sv_2mortal(newSViv(b)));
31 PUTBACK
;
32 count
= perl_call_pv("GetRatioEval", G_ARRAY | G_EVAL);
33 SPAGAIN
;
34 svp =
GvSV(gv_fetchpv("@", TRUE, SVt_PV));
35 if (SvTRUE(svp))
36 {
37 printf
("Die by division: %s\n", SvPV(svp, na)) ;
38 POPs
;
39 }
40 else
41 {
42 if (count
!= 2) croak("Whoa! \n") ;
43 printf
("%d / %d = %f\n", a, b, POPn) ;
44 printf
("%d / %d = %f\n", b, a, POPn) ;
45 }
46 PUTBACK
;
47 FREETMPS
;
48 LEAVE
;
49 }
In the code shown in Listing 26.11, the call to the Perl function
will terminate in a die()
function call. The returned value from this Perl function call
is checked in line 34. The variable we are looking at is the $@
variable in Perl. The syntax for this call is
svp = GvSV(gv_fetchpv("@",
TRUE, SVt_PV));
The value of the variable is checked in the following lines, and
the stack is adjusted with a call to pop off the string. The string
is retrieved with a call to the SvPV()
function in line 38.
In Listing 26.7 we recovered values of special variables, $<
and $(, to get the UID and
GID of the calling process via a Perl subroutine. The Perl subroutine
was simply an example of how to call a routine. Now let's see
how we can get values of special variables in Perl directly. The
call to get these values is
svp = GvSV(gv_fetchpv(variableName, defaultValue,
SVt_PV));
Let's look at the function in Listing 26.12 to see how to get
the UID and GID of a calling C program.
Listing 26.12. Function for getting the values of $<
and $( directly.
1 static int getUserInfo()
2 {
3 dSP ;
4 int tmp;
5 SV *svp;
6 PUSHMARK(sp);
7 svp = GvSV(gv_fetchpv("<",
0, SVt_PV));
8 tmp = SvIV(svp);
9 printf ("\n UID = %d",tmp);
10 svp = GvSV(gv_fetchpv("(",
0, SVt_PV));
11 tmp = SvIV(svp);
12 printf ("\n GID = %d",tmp);
13 }
The GvSV() function returns
the current value of the variable named in the first parameter.
The default value is 0 for
these calls. The returned value from each GvSV
call is a pointer from which an integer is extracted with a call
to SvIV().
The POPi, POPp,
and POPn macros are great
for getting items off the stack one at a time. To get the individual
items in the stack though, you have to use the ST()
macros. Basically, ST(n)
returns the nth item from the top of the stack. However,
you have to adjust the number of items on the stack yourself.
Listing 26.13 illustrates how the stack will look using the ST
macros with a different function. Line 39 is where the ST(i)
macro is used. The stack length is adjusted in lines 35 and 36.
Listing 26.13. Using the ST
macros.
1 /* demonstration C program */
2 /* Using the ST macros.*/
3
4 #include <stdio.h>
5 #include <EXTERN.h>
6 #include <perl.h>
7
8 static void squares(int a);
9 static PerlInterpreter *my_perl;
10
11 int main(int argc, char **argv,
char **env)
12 {
13 my_perl
= perl_alloc();
14 perl_construct(my_perl);
15 perl_parse(my_perl,
NULL, argc, argv, env);
16 getRatio(8);
17 perl_destruct(my_perl);
18 perl_free(my_perl);
19 }
20
21
22 static void Squares(int a)
23 {
24 dSP ;
25 I32 ax;
26 int i;
27 int count
;
28 ENTER
;
29 SAVETMPS;
30 PUSHMARK(sp)
;
31 XPUSHs(sv_2mortal(newSViv(a)));
32 PUTBACK
;
33 count
= perl_call_pv("squares", G_ARRAY);
34 SPAGAIN
;
35 sp -=
count ;
36 ax = (sp
- stack_base) + 1 ; /* adjust the stack */
37 if (count
!= 2) croak("Whoa! \n") ;
38 for (i
= 0; i < count; i++)
39 printf
("%d ", SvIV(ST(i))) ;
40 PUTBACK
;
41 FREETMPS
;
42 LEAVE
;
43 }
The for loop recovers only
as many values as are on the stack. If you do not want to adjust
the stack, you can remove lines 35 and 36 from this code and replace
the code in lines 38 and 39 with this:
for (i = 0; i < count; i++)
printf
("%d ", POPi) ;
Of course, the choice of which type of function to use is entirely
up to you.
In addition to calling Perl code, you can also use the eval
function to directly evaluate a Perl statement. This lets you
use a C program by itself without having the need to declare the
code for Perl elsewhere. By using C strings to hold your Perl
programs, you can create entire applications using one C source
file. Listing 26.14 presents a sample file.
Listing 26.14. Using expressions in C.
1 #include <stdio.h>
2 #include <EXTERN.h>
3 #include <perl.h>
4
5 static PerlInterpreter *my_perl;
6
7
8 /*
9 ** This is a wrapper around the eval call
10 */
11 int evalExpression(char *evaluatedString)
12 {
13 char *argv[2];
14 argv[0] = evaluatedString;
15 argv[1] = NULL;
16 perl_call_argv("_eval_",
0, argv);
17 }
18
19 main (int argc, char **argv, char **env)
20 {
21
22 /*
23 ** Plain code to do some parsing.
24 */
25 char *codeToUse[] = { "",
"-e", "sub _eval_ { eval $_[0] }" };
26 STRLEN length;
27
28 my_perl = perl_alloc();
29 perl_construct( my_perl
);
30
31 /*
32 ** Fake out the call by creating
your own argc, argv, and env
33 */
34 perl_parse(my_perl, NULL,
3, codeToUse, env);
35
36 evalExpression("$x
= 3; $y = 2; $rho= sqrt($x * $x + $y * $y);");
37 printf("x = %d, y =
%d and rho = %f \n",
38 SvIV(perl_get_sv("x",
FALSE)),
39 SvIV(perl_get_sv("y",
FALSE)),
40 SvNV(perl_get_sv("rho",
FALSE)));
41 evalExpression("$wisdom
42 = 'Able was I ere I saw
Elba'; $wisdom = reverse($wisdom); ");
43 printf("wisdom = %s\n",
SvPV(perl_get_sv("wisdom", FALSE), length));
44
45 evalExpression("$wisdom
= 'I ran a mile today, and said \
46 Here Lady Take your purse'; $wisdom
= reverse($wisdom); ");
47 printf(" %s\n",
SvPV(perl_get_sv("wisdom", FALSE), length));
48
49 evalExpression("$joke
= 'I was walking down the street when something
50 caught my eye and dragged it twenty feet'; $joke = uc($joke);
");
51 printf("%s\n",
SvPV(perl_get_sv("joke", FALSE), length));
52
53 perl_destruct(my_perl);
54 perl_free(my_perl);
55 }
Here's the output from running this program:
x = 3, y = 2 and rho = 3.605551
wisdom = ablE was I ere I saw elbA
esrup ruoy ekaT ydaL ereH dias dna ,yadot elim a nar I
I WAS WALKING DOWN THE STREET WHEN SOMETHING
CAUGHT MY EYE AND DRAGGED IT TWENTY FEET
Now let's look at some of the lines of relevance in the listing.
Lines 11 through 17 define a function that will serve as the wrapper
around the Perl eval() function.
Basically, the function evalExpression
takes one string as an argument, creates an argument vector, and
then calls the _eval_ function
with this newly created argument vector.
Then in line 25 we actually define the _eval_
function as if it was typed on the command line. The text is preserved
in the string variable codeToUse.
The perl_parse function is
then called with the codeToUse
string and a length of 3
arguments as argc. The environment
is passed in verbatim.
At line 36 we test out how to use integers and floating point
numbers in a calculation. Note how the returned values are extracted
by naming functions without $.
The $ is automatically prepended
to the variable name; therefore, you should not use it explicitly.
If you prepend $ yourself,
the value of the variable $$var,
not $var, will be extracted.
Strings are probably where you'll benefit the most when using
Perl functions from within C. Lines 42 through 51 show examples
of how to call Perl functions to reverse and change the case of
some strings. Note how the strings can cross multiple lines.
Actually, you can put in entire Perl functions instead of these
calls and have the eval operator
work on these functions as strings. This enables you to create
very powerful applications using the power of each of the languages
(C and Perl).
It's possible to use the Perl interpreter to do pattern matches
and string substitutions from within C code. Pattern matches in
Perl are easy when compared with the same process in C. This is
one area where you can use Perl to make up for the lack of pattern
matching and string substitution features in C. Here's a definition
of two functions in C that use the Perl interpreter:
- int match(char *inputString, char
*matchString)
- This function takes an input string, and attempts to match
it with the pattern in matchString.
The matchString is a string
with a regular pattern in it; for example, "/Gumb[oy]/"
or "/[Dd]onald/".
Be careful when using double quotes within patterns because you'll
have to escape them with a backslash ("\").
- int substitute(char *inputString,
char *substitution)
- This function takes an input string followed by a substitution
operation such as "s/courage/stupidity/"
or "s/ition/ate/g".
The inputString will be modified
if any substitution is made.
Listing 26.15 presents the code to define and use these functions.
Listing 26.15. Using pattern matching and substitution in C.
1 /*
2 ** Using the Perl interpreter to do pattern matching
3 ** and string substitution.
4 */
5 #include <stdio.h>
6 #include <EXTERN.h>
7 #include <perl.h>
8
9 /* Undefine this to see how it all works. */
10 #define KDEBUG 1
11
12 static PerlInterpreter *my_perl;
13
14 /*
15 ** A wrapper around the Perl eval statement
16 */
17 int doExpression(char *string)
18 {
19 char *argv[2];
20 argv[0] = string;
21 argv[1] = NULL;
22 perl_call_argv("_eval_",
0, argv);
23 }
24
25 /*
26 ** A global to this program since I am too lazy to use
mallocs
27 */
28 static char command[256];
29
30
31 /*
32 ** Do a pattern match
33 */
34 char match(char *string, char *pattern)
35 {
36 sprintf(command, "$string = '%s';
$return = $string =~ %s",
string, pattern);
37 #ifdef KDEBUG
38 printf (" %s",
command);
39 #endif
40 doExpression(command);
41 return SvIV(perl_get_sv("return", FALSE));
42 }
43
44 /*
45 ** Do a string substitution
46 */
47 int substitute(char *string, char *pattern)
48 {
49 char *bfptr = command;
50 STRLEN length;
51 sprintf(command, "$string = '%s'; $ret = ($string
=~ %s)",string,pattern);
52
53 #ifdef KDEBUG
54 printf (" %s", command);
55 #endif
56
57 doExpression(command);
58 bfptr = (char *) SvPV(perl_get_sv("string",
FALSE), length);
59 strcpy(string,bfptr);
60 return SvIV(perl_get_sv("ret", FALSE));
61 }
62
63
64 /*
65 ** The main program itself.
66 */
67 main (int argc, char **argv, char **env)
68 {
69 char *embedding[] = { "", "-e", "sub
_eval_ { eval $_[0] }" };
70 STRLEN length;
71 char *text;
72 int i,j;
73
74 my_perl = perl_alloc(); /*
Allocate the interpreter */
75 perl_construct( my_perl
); /* Call the constructor */
76 /* Fake the call to the
script to use */
77 perl_parse(my_perl,
NULL, 3, embedding, env);
78
79 /*
80 ** Do the loop
81 */
82
83 while (1) {
84 doExpression("$reply
= <STDIN>; chop $reply;");
85 text = SvPV(perl_get_sv("reply",
FALSE), length);
86 printf("reply
= %s\n", text);
87
88 if
(match(text, "/[Qq]uit|[Ee]xit/")) /* Bail out? */
89 break;
90 if
(match(text, "/[Cc]om/"))
91 {
92 printf("match:
Text contains the word 'com'\n\n");
93 substitute(text,
"s/com/commercial/g");
94 printf("\nAfter
substitution = %s\n", text);
95 }
96 else
97 printf("match:
Text doesn't contain the word Com.\n\n");
98
99 }
/* while loop ends */
100
101 /*
102 ** Clean up after yourself.
103 */
104 perl_destruct(my_perl);
105 perl_free(my_perl);
106 }
The program is derived from the code in Listing 26.14. Most of
the constructs are the same with the exception of the global command
buffer declared at line 28. You might want to consider using mallocs
within functions for a more complicated application. The KDEBUG
flag is set to 1 so as to show how the command strings are constructed.
You can comment out the code in line 10 for a less verbose output.
The match function is defined
at line 34. The command string is constructed at line 36 with
the command executed at line 40. The value of the $return
string is returned. The $return
contains the first matched pattern and will be empty if no matches
are found. If $return is
empty, 0 will be returned.
The substitute function is defined at line 47. A command string
is constructed at line 51 using the global "command"
buffer. At line 58, we retrieve the value of the $ret
variable after the substitution has been made, and we overwrite
this new string onto the input string. The length of the new string
is returned at line 60. The bulk of the work in the program is
being done in lines 83 to 99 during the while
loop. At line 84, we collect an input string from the user and
point to it with the text char *pointer.
Then we match the incoming string to see whether we have to exit
in line 88 and break out of the loop if there is a match. At line
91, we search for another pattern and, if found, substitute a
string in the input pattern.
This chapter shows ways of incorporating the Perl interpreter
into your C code. Writing a makefile involves getting the correct
paths to the libraries. The ExtUtils::embed
module can help you get these paths. The C code that utilizes
the Perl functions must initialize and maintain a PerlInterpreter
object. Calls from C into Perl have to maintain a stack on which
values are sent into and retrieved from functions. Both scalar
and array values can be returned from Perl functions, and the
calling routine has to be aware of how to handle these inputs.
The Perl functions being called can either reside on disk or can
be embedded in C strings. When combining code from both these
languages, you have to balance the division to get the most out
of each language by using their strong points. For example, use
Perl for string manipulation and use C for coding complex operations
involving calculations.
Chapter 27
Writing Extensions in C
CONTENTS
In this chapter you'll work with the Perl XS
language, which is used to create an interface between
Perl and a C library. Such interfaces are called extensions
to Perl because they enable your code to look and feel just like
it is a part of Perl. Extensions are useful in appending extra
functionality to Perl. This chapter covers the basics of writing
extensions. The examples are simple enough to build on in order
to create your own extensions library.
In Perl, XS refers to a programming language interface used to
create an interface between C code and Perl scripts. Using the
XS API, you can create a library that can be loaded dynamically
into Perl.
The XS interface defines language components that wrap around
Perl constructs. To use the XS language, you need the xsubpp
compiler to embed the constructs for you. The base construct in
the XS language is the XSUB
function. The XSUB function
is called when calls are made to pass data and control between
Perl and C code. Basically, Perl scripts call the XSUB
routines to get to the C code in the libraries encapsulated by
the XSUB functions.
To ensure that correct data types are mapped between C and Perl
scripts, the XS compiler does a mapping of one C type of variable
to a type in Perl. The mapping is maintained in a file called
typemap. When you're looking
for extension files, it's often instructive to see how files are
mapped by using the typemap
file in the same directory as the source file. typemap
files are covered later in this chapter.
You may be asking yourself why someone would want to write an
extension in C when Perl is a perfectly good working language.
For one thing, Perl is slow compared to C. Your C compiler can
generate really tight code. All that power does have drawbacks.
Another reason is that you might already have source code written
and working in C, and porting this existing code to Perl would
not make much sense. Also, it's possible to write code that can
be accessed with Perl and C if you write the interfaces to your
core functions correctly.
The best way to show the creation of an extension is by example.
This section steps you through the creation of the futureValue
world function for Perl.
Go to the directory where you installed the Perl distribution.
This is important. Do not try this in any other directory or you'll
get errors.
For Step 2, you have to run the header to extension program h2xs.
To obtain a list of the options for this program, use the -h
option, as shown here:
$ h2xs -h
h2xs [-Acfh] [-n module_name] [headerfile [extra_libraries]]
-f Force creation of
the extension even if the C header does not exist.
-n Specify a name to
use for the extension (recommended).
-c Omit the constant()
function and specialised AUTOLOAD from the XS file.
-A Omit all autoloading
facilities (implies -c).
-h Display this help
message
extra_libraries
are any
libraries that might be needed for loading the
extension,
e.g. -lm would try to link in the math library.
Run h2XS -n Finance. This
creates a directory named Finance,
possibly under the subdirectory ext/
if it exists in the current working directory. Four files are
created in the Finance directory:
MANIFEST, Makefile.PL,
Finance.pm, and Finance.xs.
Here's what the output on your terminal will look like:
$ h2xs -n Finance
Writing ext/Finance/Finance.pm
Writing ext/Finance/Finance.xs
Writing ext/Finance/Makefile.PL
The MANIFEST file in the
ext/Finance directory contains
the names of the four files created. You have to change directories
to ./ext/Finance to be able
to work with these four files. Also, depending on who installed
your Perl distribution, you might have to run as root.
The contents of file Makefile.PL
are shown in Listing 27.1.
Listing 27.1. The contents of Makefile.PL.
1 use ExtUtils::MakeMaker;
2 # See lib/ExtUtils/MakeMaker.pm for details of how to
influence
3 # the contents of the Makefile that is written.
4 WriteMakefile(
5 'NAME' =>
'Finance',
6 'VERSION' =>
'0.1',
7 'LIBS' =>
['-lm'], # e.g., '-lm'
8 'DEFINE' =>
'', # e.g., '-DHAVE_SOMETHING'
9 'Inc' =>
'', # e.g., '-I/usr/include/other'
10 );
The h2xs script also creates
a .pm file. The contents
of file Finance.pm are shown
in Listing 27.2. The Finance.pm
file is where you add your exports and any Perl code.
Listing 27.2. The module file: Finance.pm.
1 package Finance;
2
3 require Exporter;
4 require DynaLoader;
5 require AutoLoader;
6
7 @ISA = qw(Exporter DynaLoader);
8 # Items to export into callers namespace by default. Note:
do not export
9 # names by default without a very good reason. Use EXPORT_OK
instead.
10 # Do not simply export all your public functions/methods/constants.
11 @EXPORT = qw(
12
13 );
14 sub AUTOLOAD {
15 # This AUTOLOAD is used to 'autoload'
constants from the constant()
16 # XS function. If a
constant is not found then control is passed
17 # to the AUTOLOAD in AutoLoader.
18
19 local($constname);
20 ($constname = $AUTOLOAD) =~ s/.*:://;
21 $val = constant($constname, @_
? $_[0] : 0);
22 if ($! != 0) {
23 if ($! =~ /Invalid/) {
24 $AutoLoader::AUTOLOAD
= $AUTOLOAD;
25 goto
&AutoLoader::AUTOLOAD;
26 }
27 else {
28 ($pack,$file,$line)
= caller;
29 die
"Your vendor has not defined Finance macro
$constname, used at $file line $line.
30 ";
31 }
32 }
33 eval "sub $AUTOLOAD { $val
}";
34 goto &$AUTOLOAD;
35 }
36
37 bootstrap Finance;
38
39 # Preloaded methods go here.
40
41 # Autoload methods go after _ _END_ _, and are processed
by the autosplit program.
42
43 1;
44 _ _END_ _
All scripts which use Finance.pm
will now have to tell Perl to use functions in the Finance.pm
extension with the following command:
use Finance;
When Perl sees this use command,
it searches for a Finance.pm
file of the same name in the various directories listed in the
@Inc array. If it cannot
find the file, Perl stops with an error message.
The .pm file extension generally
requests that the Exporter and Dynamic Loader extensions also
be loaded. You need them for exporting functions and dynamic loading.
Perl uses the @ISA array
to get any methods that are not found in the current package.
After this set, the library is loaded as an extension into Perl.
There are two files to look at in the Finance
example we just created. The Finance.xs
file (Listing 27.3) holds the C routines that contain all the
C code for the extension, and the Finance.pm
file (Listing 27.2) contains routines that tell Perl how to load
this extension and what functions are exported.
In Step 3, you have to generate a makefile.
Generating and invoking the make
command makefile will create
a working version of the library Finance.so
in the ../../lib/ext/Finance
directory. After testing, you can move the finished versions of
these files to the /usr/lib
or /usr/local/lib tree. In
all further testing in this section, you must point the @Inc
array to the ../../lib/ext/Finance
location for this finance.so
file.
You may also see a blib directory
in the ext/Finance directory.
The man page templates for
your extensions are kept here.
Finally, the Finance.xs file
where you place all your code for extension in C is shown in Listing
27.3.
Listing 27.3. The initial Finance.xs
file.
1 #ifdef _ _cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #ifdef _ _cplusplus
8 }
9 #endif
10
11 static int
12 not_here(s)
13 char *s;
14 {
15 croak("%s not implemented
on this architecture", s);
16 return -1;
17 }
18
19 static double
20 constant(name, arg)
21 char *name;
22 int arg;
23 {
24 errno = 0;
25 switch (*name) {
26 }
27 errno = EINVAL;
28 return 0;
29
30 not_there:
31 errno = ENOENT;
32 return 0;
33 }
34
35 MODULE = Finance PACKAGE
= Finance
36
37 double
38 constant(name,arg)
39 char * name
40 int arg
Now that you have created the necessary files for your own Perl
extension, you can move to Step 3, which involves adding your
own code to the newly generated extension files. Add some simple
futureValue world application
code to the Finance.xs file.
Listing 27.4 shows what Finance.xs
looks like with the code addition. Be sure to create this file
because you'll be using it throughout the rest of the chapter.
Listing 27.4. After code is added to Finance.xs.
1 #ifdef _ _cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #ifdef _ _cplusplus
8 }
9 #endif
10
11 static int
12 not_here(s)
13 char *s;
14 {
15 croak("%s not implemented
on this architecture", s);
16 return -1;
17 }
18
19 static double
20 constant(name, arg)
21 char *name;
22 int arg;
23 {
24 errno = 0;
25 switch (*name) {
26 }
27 errno = EINVAL;
28 return 0;
29
30 not_there:
31 errno = ENOENT;
32 return 0;
33 }
34
35 MODULE = Finance PACKAGE
= Finance
36
37 double
38 constant(name,arg)
39 char * name
40 int arg
41
42 double
43 futureValue(present,rate,time)
44 double present
45 double rate
46 double time
47
48 CODE:
49 double d;
50 extern double pow(double
x, double y);
51
52 d = present * pow((1.0
+ rate),time);
53 /* printf("\n
Future Value = %f \n", d); */
54 RETVAL = d;
55
56 OUTPUT:
57 RETVAL
58
59 double
60 presentValue(future,rate,time)
61 double future
62 double rate
63 double time
64
65 CODE:
66 double d;
67 extern double pow(double
x, double y);
68
69 d = future / pow((1.0
+ rate),time);
70 /* printf("\n
Present Value = %f \n", d); */
71 RETVAL = d;
72
73 OUTPUT:
74 RETVAL
75
76 void
77 Gordon(d,r,g)
78 double d
79 double r
80 double g
81
82 CODE:
83 /*
Return Gordon Growth Model Value of stock */
84 g = d / (r -g);
85 printf("\n g
= %f", g);
86
87 void
88 depreciateSL(p,s,n)
89 double p
90 double s
91 double n
92
93 PpcODE:
94 double sum;
95 double value[10];
96 double dep;
97 int i;
98 int in;
99 in = (int)n;
100 if ((n < 10) &&
(n > 0))
101 {
102 EXTEND(sp,in);
103 sum =
p;
104 printf("value
= %f for %d years \n", sum,in);
105 dep
= (sum - s)/ n;
106 for
(i=0; i<n; i++)
107 {
108 sum
-= dep;
109 printf("value
= %f \n", sum);
110 value[i]
= sum;
111 PUSHs(sv_2mortal(newSViv(sum)));
112 }
113 }
A function to calculate the future value of an investment is defined
in line 43. The function to calculate the present value of money
to be received in the future from an investment is defined starting
at line 60. Both functions return one value and require three
arguments, which are defined one per each line following the function
declaration. For example, for the present value function in line
60, the three arguments must be defined in one line as
double future, rate, time;
At line 77, I define a Gordon Growth model function for a stock.
This function only prints something and does not return any values.
At line 88, I define a straight line depreciation model function
that returns more than one value on the calling stack.
Caution |
Be careful to put the type of function and the name of the function on separate lines. In other words, do not shorten the two lines into one. The return parameter and the function name must be on two lines for the XS specification. Any arguments to the
function would have be to listed one at a time on each line following the function name.
|
Next, run the command perl Makefile.PL.
This creates a real makefile, which make
needs. The Makefile.PL checks
to see whether your Perl distribution is complete and then writes
the makefile for you.
If you get any errors at this point, you should check to see whether
your Perl distribution is complete. As a check, try running the
Makefile.PL script as root.
If your Perl distribution was installed by root,
you may not have permission to overwrite some files. It won't
hurt to try.
If you do not get any errors, proceed.
Run the makefile on your newly created Makefile.
The following output should be pretty close to what you see:
# make
umask 0 && cp Finance.pm ../../lib/Finance.pm
../../perl -I../../lib -I../../lib ../../lib/ExtUtils/xsubpp
-typemap ../../lib/ExtUtils/typemap Finance.XS
>Finance.tc && mv Finance.tc Finance.c
cc -c -D_ _USE_BSD_SIGNAL -Dbool=char -DHAS_BOOL
-O2 -DVERSION=\"0.1\" -fpic -I../.. Finance.c
Running Mkbootstrap for Finance ()
chmod 644 Finance.bs
LD_RUN_PATH="" cc -o ../../lib/auto/Finance/Finance.so
-shared
-L/usr/local/lib Finance.o
chmod 755 ../../lib/auto/Finance/Finance.so
cp Finance.bs ../../lib/auto/Finance/Finance.bs
chmod 644 ../../lib/auto/Finance/Finance.bs
Wait! Before you execute this gem of a script shown above, look
at the output in Listing 27.6. The shared version of Finance.so
is in the directory ../../lib/auto/Finance/Finance.so.
It is important that you copy Finance.so
to your @Inc path. It's important
at this point to either modify the @Inc
array in your scripts that use Finance.pm
or, by default, point to a known test location where this .so
file will reside. Perl will search the directories listed in @Inc
to load the extension module.
Now, in the Test1 directory,
create the test script shown in Listing 27.5 and name it t.pl.
Listing 27.5. The test program.
1 #!/usr/bin/perl
2
3 use Finance;
4
5 Finance::Gordon(50,4,2);
6 print "\n";
7
8 #
9 #
10 #
11 $pv = 1000.0;
12 $time = 10 * 12;
13 $rate = 0.05 / 12;
14 $fv = Finance::futureValue($pv,$rate,$time);
15 printf "\n Future Value of %f after %f periods accruing
interest ",
16 $pv,
$rate;
17 printf "\n for %f months will be r %f \n",
18 $time,
$fv;
19
20 printf "\n Let us go backward and see if we get the same
numbers";
21 $pvBack = Finance::presentValue($fv,$rate,$time);
22 printf "\n Present Value ", $pvBack;
23
24 printf "\n Difference = %f", ($pv - $pvBack);
25
26 printf "\n ------- see any difference? --------- \n"
;
Notice that Finance::Gordon
is used to explicitly call the Gordon
Growth Model function (see line 5). Look up the formula
in your finance textbook if you don't believe me. It would be
cumbersome to keep typing in Finance::
to all your functions. Add the declaration to the @EXPORT
array in Finance.pm and remake.
Now you can use the function Gordon
by itself. The @EXPORT array
in the .pm file tells Perl
which of the extension's routines should be placed in the calling
package's own name space.
There are some things you should be aware of before you export
everything in your module. Sure, it saves you typing and makes
the code easier to read by not having all those Finance::
prefixes everywhere. However, what about the same function name
residing in both the main and the modules? In this case, the function
in the main may prevail. Why create an ambiguity when the choice
of a good name for a function will suffice? Also, it's not a good
idea to export every function in your extension. After all, the
idea behind the extension is to hide some of the functionality
and intricacies in the extension from the application that is
using this extension module.
Most of the time you do not want to export the names of your extension's
subroutines because they might accidentally clash with other modules'
subroutines from other extensions or from the calling program
itself.
If you examine the makefile for your extension, you'll see a call
to a program called xsubpp.
This is a preprocessor compiler for XS code.
The compiler xsubpp takes
the XS code in the .xs file,
converts it into C code, and places it in a file whose suffix
is .c. The C code created
makes heavy use of the C functions within Perl.
Tip |
Make sure the xsubpp compiler is in your path and that the first line in the file points to /usr/bin/perl and not to .miniperl (if you did not
install miniperl).
|
An XSUB function is just
like a C function in that it takes arguments and returns one or
more single values (if not declared void). Values may also be
returned via pointers to arguments passed to the function.
Now move on to something a little bit more exotic and create a
function that takes arguments and returns something. This function
calculates and returns the Julian day given a calendar day. The
Julian day calculation is very important in astronomical calculations
since it's a reference counter from all the days since January
1, 4713 B.C. and was founded by the French scholar Joseph Scaliger
(1540-1609) in 1583 A.D. The formula for calculating the Julian
day is given in forms in just as many astronomical texts. One
version of this formula is:
Julian Day = 367 * YEAR - 7 * (YEAR + (M + 9)/12)4 +
(275
* M / 9) + 1721013.5;
Don't try to shorten the formula by reducing it to an algebraic
equivalent since the formula relies on dropping bits off the right
side of the decimal point. One such way of implementing this formula
is the function for calculating the Julian day, as shown in Listing
27.6.
Listing 27.6. The Julian.c
file.
1 #include <math.h>
2
3 long JulianDay( int month, int day, int year)
4 {
5 double t1, t2; long jd;
6 t1 = 7 * floor((year + floor(month * 9)/12)/4);
7 t2 = floor(275 * month / 9);
8 jd = (long) (floor(367 * year - t1 + t2 + day + 1721013.5));
9 return(jd);
10 }
11 /* SAMPLE USAGE
12 main(int argc, char *argv[])
13 {
14 long day1, day2;
15 day1 = JulianDay(7,21,1962);
16 day2 = JulianDay(2,2,1996);
17 printf("\n Thou are only %d days old", day2 - day1);
18 }
19 */
Run h2xs -A -n Julian as
before to get the Julian module started. This creates the ext/Julian
directory with the necessary files. This time, however, you'll
be adding a lot more code into the functions in Julian.xs,
as shown in Listing 27.7.
Listing 27.7. Adding functions to Julian.xs.
1 #ifdef _ _cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #ifdef _ _cplusplus
8 }
9 #endif
10
11 MODULE = Julian PACKAGE
= Julian
12
13 #include <math.h>
14
15 long
16 JulianDay( month, day, year)
17 int month
18 int day
19 long year
20
21 CODE:
22 long
jul;
23 double t1, t2;
24 t1 = 7 * floor((year + floor(month * 9)/12)/4);
25 t2 = floor(275 * month / 9);
26 jul = (long) (floor(367 * year - t1 + t2 + day + 1721013.5));
27
28 }
29 RETVAL
= jul;
30 OUTPUT:
31 RETVAL
Note that each line containing the arguments after the declaration
of JulianDay is indented
one tab. It is not necessary to have a tab between the type of
variable and the name of the variable. Also note that that there
is no semicolon following the declaration of each variable.
Edit the file Makefile.PL
so that the corresponding line looks like this:
'LIBS' =>
['-lm'], # e.g., '-lm'
Notice that an extra library to link in has been specified in
this case, the math library, libm.
You'll learn later in this chapter how to write XSUBs
that can call every routine in a library.
Generate the makefile and
run make. A test script for
running this program is shown in List-ing 27.8.
Listing 27.8. Testing the Julian
Day module.
1 #!/usr/bin/perl
2
3 use Julian;
4
5 $m1 = 07;
6 $d1 = 21;
7 $d2 = 22;
8
9 $yr1 = 1996;
10 $yr2 = 1996;
11
12 $jd1 = &Julian::JulianDay($m1,$d1,$yr1);
13 $jd2 = &Julian::JulianDay($m1,$d2,$yr2);
14
15 print "Day 1: $jd1 \n";
16 print "Day 2: $jd2 \n";
17 print "Delta: ",$jd2 - $jd1, "\n" ;
Now that you've learned some of the ways to create and use C extensions,
here's how to put them all together. First of all, look at the
Julian.c file in Listing
27.9, put together by the Perl script.
The function is called XS,
and the arguments are specified via the dXSARGS
keyword.
Listing 27.9. The Julian.c
file.
1 /*
2 * This file was generated automatically by
xsubpp version 1.923 from the
3 * contents of Julian.xs. Don't edit this file,
edit Julian.XS instead.
4 *
5 * ANY chANGES
MADE HERE WILL BE LOST!
6 *
7 */
8
9 #ifdef _ _cplusplus
10 extern "C" {
11 #endif
12 #include "EXTERN.h"
13 #include "perl.h"
14 #include "XSUB.h"
15 #ifdef _ _cplusplus
16 }
17 #endif
18
19 #include <math.h>
20 XS(XS_Julian_JulianDay)
21 {
22 dXSARGS;
23 if (items != 3)
24 croak("Usage:
Julian::JulianDay(month, day, year)");
25 {
26 int month
= (int)SvIV(ST(0));
27 int day
= (int)SvIV(ST(1));
28 long year
= (long)SvIV(ST(2));
29 long RETVAL;
30 long
jul;
23 double
t1, t2;
24 t1
= 7 * floor((year + floor(month * 9)/12)/4);
25 t2
= floor(275 * month / 9);
26 jul
= (long) (floor(367 * year - t1 + t2 + day + 1721013.5));
27 }
28 RETVAL
= jul;
29 ST(0) = sv_newmortal();
30 sv_setiv(ST(0),
(IV)RETVAL);
31 }
32 XSRETURN(1);
33 }
34
35 #ifdef _ _cplusplus
36 extern "C"
37 #endif
38 XS(boot_Julian)
39 {
40 dXSARGS;
41 char* file = _ _FILE_ _;
42
43 newXS("Julian::JulianDay",
XS_Julian_JulianDay, file);
44 ST(0) = &sv_yes;
45 XSRETURN(1);
46 }
The meaning of keywords such as newXS,
SvIV, and so on in the output
C file are explained in Chapter 25, "Perl
Internal Files and Structures." However, for the moment,
concentrate on the compiler itself and how it expects input.
The functions compiled by the xsubpp
compiler are referred to as XSUB.
You specify the parameters that are passed into the XSUB
just after you declare the function return value and name. The
list of parameters looks very C-like, but the lines must be indented
by a tab stop, and each line should not have an ending semicolon.
The list of output parameters occurs after the OUTPUT:
directive. The default value returned is RETVAL.
The use of RETVAL tells Perl
that you want to send this value back as the return value of the
XSUB function. You still
have set RETVAL to something.
You can also specify which variables used in the XSUB
function should be placed into the respective Perl variables that
are passed in.
The xsubpp compiler uses
rules to convert from Perl's internal data types to C's data types.
These rules are stored in the typemap
file. The rules in typemap
contain mappings for converting ints,
unsigned ints, and so on
into Perl scalars. Arrays are mapped to char**
or void pointers, and so
on. The typemap file with
all the mappings is located in the ExtUtils
directory under the Perl installation.
The typemap file is split
into three sections. The first section is a mapping of various
C data types into a tag value. The second section is for converting
input parameters to C, and the third is for outputting parameters
from C to Perl.
Take a look at Listing 27.9 again. Note the SvIV
for the month declaration.
Now look in the typemap file
for the declaration of int.
You'll see it defined as T_IV.
Now go to the second INPUT
part in the file to see how T_IV
is mapped for input. You'll see the following lines, which map
the integer from the Perl variable:
T_IV
$var = ($type)SvIV($arg);
Similarly, in the OUTPUT
section of the typemap file,
you'll see the following lines to generate a returned value. This
fragment places an integer into the ST
array (which is indexed from 0
on up for all the incoming and outgoing arguments of a function):
T_IV
sv_setif($arg, (IV)$var);
Tip |
With C pointers, the asterisk indirection operator (*) defines the type foo pointer. When using the address of a variable, the ampersand (&)
is considered part of the variable, and you should use a pointer type.
|
If you forgot to create the typemap
file, you might see output that looks like this:
Error: 'const char *' not in typemap
in Julian.xs, line XXX
This error means that you have used a C data type that xsubpp
doesn't know how to convert between Perl and C. The solution is
to create a custom typemap
file that tells xsubpp how
to do the conversions.
You can define your own typemap
entries if you find certain parameters in the file that you cannot
find in the existing typemap
file. For example, the type double
is understood by Perl, but not double
*. In this case you have to make an entry in the typemap
file to convert the pointer to double
to something Perl will understand. Try a void
pointer.
All Perl extensions require a Perl module with a call to the bootstrap
function, which loads the extension into Perl. The module's functions
are two-fold: Export all the extension's functions and global
references to variables to the Perl script using the extension,
and load the XSUBs into Perl
using dynamic linking. Thus, you require two modules: the Exporter
to export your functions and the DynaLoader
for dynamic loading. See the following example for the Julian
package:
package Julian; #
my package
require Exporter; # <--- so that I can export
functions
require DynaLoader; # <--- for loading extensions
@ISA = qw(Exporter DynaLoader); #inherit functionality.
@EXPORT = qw( JulianDay ); # to reduce use of Julian::
in scripts.
bootstrap Julian; # Load the extension in to
Perl
1;
Parameters are passed into an XSUB
function via an argument stack. The same stack is used to store
the XSUB's return value.
All Perl functions are stack oriented and use indexes in their
own stack to access their variables.
The stacks are organized bottom up and can be indexed using the
ST(index) macro. The
first position on that stack that belongs to the active function
is referred to as index 0 for that function. The positions on
the stack are referred to as ST(0)
for the first item, ST(1)
for the next, and so on. The incoming parameters and outgoing
return values for an XSUB
are always position 0. Parameters are pushed left to right.
Caution |
ST(x) is a macro. Be careful not to do something like this when using it: ST(x++). Depending on how the macro is defined, you may increment x
more than once. It won't now, but it just might. Handle macros with care.
|
The OUTPUT section of the
xs file is where you place
return values. The return value is always ST(0).
However, this value will not be set unless the OUTPUT
section with RETVAL is defined.
You must have the two lines in a function to get it to return
a value:
OUTPUT:
RETVAL
You also have to remember to set RETVAL
somewhere along the code to have a value to return. The type of
RETVAL is the type of the
function you declared at the top. So, the JulianDay
function has a long RETVAL,
whereas the futureValue function
has a double RETVAL.
For return types of void,
the RETVAL variable is not
defined and you cannot use it.
Input parameters in an XSUB
are normally initialized with their values from the values pushed
on the argument stack at the time of the call. Entries in the
typemap file are used to
map the Perl values into their C counterparts in the XSUB
function. You can use code that would be generated by the xsubpp
compile directly to gain access to a variable. For example, in
the following function, the first argument is accessed via the
SvPV map function:
GetDayOfWeek(julianDay,dayOfWeek)
long julianDay = (long)SvPV(ST(0),na)
long dayOfWeek = 0
In this example, dayOfWeek
is assigned to a value of 0
as the default value. This is done so that if nothing is passed
in for dayOfWeek, then it
will be set to 0. Defensive
programming like this makes the package easier to use.
You can even place assignments in the parameter list, like this:
DayOfWeek(julianDay,dayOfWeek = 0)
long julianDay = (long)SvPV(ST(0),na)
long dayOfWeek
The default values set in the parameters may only be a number
or a string, not pointers. Also, you can define such values from
a right-to-left order in the parameter list. Thus, the following
line would cause unspeakable errors from xsubpp:
DayOfWeek(dayOfWeek = 0, julianDay)
To allow the XSUB for DayOfWeek()
to have a default date value,
you could rearrange the parameters to the XSUB.
A Perl program will then be able to call DayOfWeek()
with either of the following statements:
$status = DayOfWeek( $julianDay );
$status = DayOfWeek( ); # Force it default to
jday of 0
The code in the Julian.xs
file would look like the following:
int
DayOfWeek(jday = 0)
long jday;
CODE:
if (jday == 0) {
RETVAL
= 0;
}
else {
RETVAL
= (jday % 7);
}
OUTPUT:
RETVAL
The XSUB code generated for
this segment of code would look this:
XS(XS_Julian_DayOfWeek)
{
dXSARGS;
if (items < 0 || items > 1)
croak("Usage: Julian::DayOfWeek(jday
= 0)");
{
long jday;
int RETVAL;
if (items < 1)
jday = 0;
else {
jday = (long)SvIV(ST(0));
}
if (jday == 0) {
RETVAL
= 0;
}
else {
RETVAL = (jday % 7);
}
ST(0) = sv_newmortal();
sv_setiv(ST(0), (IV)RETVAL);
}
XSRETURN(1);
}
In this code fragment, the special variable items
tells the routine how many parameters have been passed into the
function. The items variable
is tested to see how to initialize jday
in this example. The sv_newmortal()
function is used to clear out the return values for this XSUB
function.
The use of ellipses (...)
for passing variable-length argument lists is also supported in
XSUBs. Your function can
easily get the number of arguments passed into it by looking at
the special items variable.
The items keyword is a reserved
variable and the xsubpp compiler
supplies items for all XSUBs.
Using the items variable
lets you accept an unknown number of arguments in your XSUB
function.
There are several special keywords in the .xs
file that can also be used when writing extensions.
The MODULE keyword is used
to start the XS code and to specify the name of the package currently
being defined. There is only one MODULE
keyword per .xs file. All
text before the MODULE keyword
is not processed in any way by xsubpp.
Do not modify the code before the MODULE
keyword. If you have to add code, it will be passed through to
the final C file.
Here's the syntax for the MODULE
keyword:
MODULE packageName
The packageName is used as
the name of the bootstrap
function for this module extension. The MODULE
keyword is generated for you by xsubpp.
On occasion, you may have more than one package per module. In
this case, the PACKAGE keyword
is used to indicate which package within the module contains the
code that follows. Generally, the name following the PACKAGE
keyword is the same as that following the MODULE
keyword.
The PACKAGE keyword is used
with the MODULE keyword and
must follow on the same line as the MODULE
keyword. You have to edit the .xs
file yourself to make sure which package gets which function.
The CODE: keyword is used
to indicate where the real C code for a function begins. Use just
C code until you start a new block with another keyword, such
as OUTPUT:. You can use C
comments (/*...*/), ampersands,
and so on, and they will not be touched by the xsubpp
compiler.
xsubpp matches certain C
preprocessor directives that are allowed within the CODE:
block. It also matches #
used for Perl comments. The compiler passes the preprocessor directives
that it recognizes through to the final C file untouched and will
remove the commented lines. Comments can be added to XSUBs
by placing # at the beginning
of the line, too. Nested comments are not supported.
Be careful not to make the comment look like a C preprocessor
directive! The xsubpp compiler
could be confused if a Perl comment begins to look like a C preprocessor
directive. The following is a bad idea:
#define a variable
Is the above line a comment or a C statement? I do not know how
this will be interpreted.
If you are going to mess with the argument stack, though, you'll
want to use the PpcODE keyword,
which will be discussed later in the chapter.
The OUTPUT: keyword specifies
the return values from a function. You have seen it used earlier
in the case of the RETVAL
assignment as a return. The OUTPUT:
keyword generates code that does the mapping of the XSUB
function's variables back to those in the Perl program calling
XSUB. This keyword is used
after the code in the CODE:
area. The RETVAL variable
is not the default return variable in the CODE:
area. Only by specifying it after the OUTPUT:
keyword are you letting xsubpp
know that it's a return variable for this function.
The OUTPUT: keyword also
lists the input parameters for use as output variables. This may
be necessary when a parameter has been modified within the function
and the programmer would like the update to be seen by Perl.
Say that you define a function, which returns the day of the week,
given an isFriday() function
in the Julian package. The
function returns true (1)
if the day is a Friday. The day of the week is returned in the
second parameter passed to the function. The function is shown
in the Julian.xs file as
this:
int
IsFriday(jDay, dayOfWeek)
long jDay
int dayOfWeek = NO_INIT
CODE:
int
dw;
dw
= (int)(jDay % 7);
if
(dw == 3) RETVAL = 1;
else
RETVAL = 0;
dayOfWeek
= dw;
OUTPUT:
dayOfWeek
RETVAL
This example uses a NO_INIT
keyword to show that the dayOfWeek
is an output value. The xsubpp
compiler normally generates code to read the values of all function
parameters from the argument stack and assign them to C variables
upon entry to the function. NO_INIT
tells the compiler that these passed parameters are used for output
rather than for input and that they are assigned before the function
terminates. Thus, the function isFriday()
uses the dayOfWeek variable
only as an output variable and does not care about its initial
contents.
The PpcODE: keyword can be
used instead of the CODE:
keyword. The PpcODE: keyword
tells the xsubpp compiler
that the code in the XSUBs
will be modifying the return stack itself. You'll use the PpcODE:
keyword to return lists instead of values. Only void
functions allow the use of PpcODE:
keywords.
Look at the following section of code from the Finance.pm
module and extension. It returns the straight line depreciation
list for an asset. The function is called depreciateSL:
void
depreciateSL(p,s,n)
double p
double s
double n
PpcODE:
double sum;
double value[10];
double dep;
int i;
int in;
in = (int)n;
if ((n < 10) && (n >
0))
{
EXTEND(sp,in);
sum =
p;
printf("value
= %f for %d years \n", sum,in);
dep
= (sum - s)/ n;
for
(i=0; i<n; i++)
{
sum
-= dep;
printf("value
= %f \n", sum);
value[i]
= sum;
PUSHs(sv_2mortal(newSViv(sum)));
}
}
Note the use of the PpcODE
variable to show that you will be messing with the stack. The
EXTEND(sp,n) macro is used
to make room on the argument stack for n
return values with the call to EXTEND(sp,n).
The PpcODE: directive causes
the xsubpp compiler to create
a stack pointer called sp,
which is conveniently used in the EXTEND()
call. The values are then pushed onto the stack with the PUSHs()
macro, with the value returned from the sv_2mortal()
call to map the value to the stack.
The way to call this function is as follows in Listing 27.10:
Listing 27.10. Using the Julian.xs
file.
1 #!/usr/bin/perl
2 use Finance;
3 #
4 # Demonstrate the return value back as list
from an extension
5 #
6 $present = 900;
7 $time = 5;
8 $salvage = 70;
9 print "\n -============= first part ===============-
\n";
10 print "First assign it all back to a list";
11 @deplist = Finance::depreciateSL($present,$salvage,$time);
12 $n = 0;
13 foreach $i (@deplist) {
14 print "\n Year ", $n,
" Returned Value = ", $i;
15 $n++;
16 }
17 print "\n -============= second part ===============-
\n";
18 print "Now with explicit values \n";
19 ($y1,$y2,$y3,$y4,$y5) = Finance::depreciateSL($present,$salvage,$time);
20 print "Returned 1 " . $y1 . "\n";
21 print "Returned 2" . $y2 . "\n";
22 print "Returned 3 " . $y3 . "\n";
23 print "Returned 4 " . $y4 . "\n";
24 print "Returned 5 " . $y5 . "\n";
Lines 13 through 15 run a for
loop to test different values for a Julian day. Here's the output
from this script:
-============= first part ===============-
First assign it all back to a listvalue
= 900.000000 for 5 years
value = 734.000000
value = 568.000000
value = 402.000000
value = 236.000000
value = 70.000000
Year 0 Returned Value = 734
Year 1 Returned Value = 568
Year 2 Returned Value = 402
Year 3 Returned Value = 236
Year 4 Returned Value = 70
-============= second part ===============-
Now with explicit values
value = 900.000000 for 5 years
value = 734.000000
value = 568.000000
value = 402.000000
value = 236.000000
value = 70.000000
Returned 1 734
Returned 2568
Returned 3 402
Returned 4 236
Returned 5 70
In Perl, there are times when you'll want to return empty or undefined
lists. You have to use the PpcODE
block, not the CODE: block.
To return empty lists, just return nothing. The Perl code sends
back a pointer to any empty list.
For return undef, you have
to set the value of ST(0)
to undef. You can use the
sv_newmortal() call to initialize
a return value to undef and
set it to ST(0).
ST(0) = sv_newmortal(); /*
Undefine the return value. */
In later sections of the code, you can use the sv_setnv()
function to set the value to something else if you want. Here's
the syntax for this call:
sv_setnv(ST(index), value);
Alternatively, you can set the ST(index)
value to sv_undef, where
a pointer to list in the ST(index)
was expected. More than likely, the index value is 0,
unless you are returning references to arrays. For example, to
return an undefined list, use this statement:
ST(0) = &sv_undef;
Note |
Remember that if you have to use these constructs you have to use the PpcODE block, not the CODE: block.
|
The BOOT: keyword is used
to add code to the extension's bootstrap
function. The bootstrap function
is generated by the xsubpp
compiler and normally holds the statements necessary to register
any XSUBs with Perl. With
the BOOT: keyword, the programmer
can tell the compiler to add extra statements to the bootstrap
function.
This keyword may be used any time after the first MODULE
keyword and should appear on a line by itself. The first blank
line after the keyword terminates the code block. A sample usage
is shown here:
BOOT:
# The following message will be printed when the bootstrap function
# executes.
printf("LOADING JULIAN\n");
The listing of Julian.xs
using the BOOT: and other
keywords is shown in Listing 27.11.
Listing 27.11. The Julian.xs
file.
1 #ifdef _ _cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #ifdef _ _cplusplus
8 }
9 #endif
10
11 MODULE = Julian PACKAGE
= Julian
12
13 BOOT:
14 printf("\n LOADING
JULIAN");
15
16 #include <math.h>
17
18 int
19 IsFriday(jDay, dayOfWeek)
20 long jDay
21 int dayOfWeek = NO_INIT
22
23 CODE:
24 int
dw;
25 dw
= (int)(jDay % 7);
26 if
(dw == 3) RETVAL = 1;
27 else
RETVAL = 0;
28 dayOfWeek
= dw;
29 OUTPUT:
30 dayOfWeek
31 RETVAL
32
33 long
34 JulianDay( month, day, year)
35 int month
36 int day
37 long year
38
39 CODE:
40 long
jul;
23 double t1, t2;
24 t1 = 7 * floor((year + floor(month * 9)/12)/4);
25 t2 = floor(275 * month / 9);
26 jul = (long) (floor(367 * year - t1 + t2 + day + 1721013.5));
27
28 RETVAL
= jul;
29 OUTPUT:
30 RETVAL
31
32 int
33 DayOfWeek(jday = 0)
34 long jday;
35
36 CODE:
37
38 if (jday == 0) {
39 RETVAL
= 0;
40 }
41 else {
42 RETVAL = (jday % 7);
43 }
44
45 OUTPUT:
46 RETVAL
Extensions to Perl are written in the XS language. Templates for
creating the modules are written by the h2xs
program. Module-specific Perl is kept in the *.pm
file, and the C code is kept in the .xs
file. The xsubpp program
parses the .xs file to generate
a C file, which in turn is compiled and linked to form the shared
library (with an .so extension).
xsubpp expects the .xs
files to follow the XS language syntax and specification. After
compilation, the .so files
with the extension code can be moved into your installation directory.
|