Dear Perl-creators, -fans and -supporters:
Recently I tried (and eventually succeeded) to include a C library of my own
(for all sorts of date calculations, in agreement with the ISO/R 2015-1971
and DIN 1355 norms) as a (dynamically linked) package into Perl 5.
Unfortunately, it was rather difficult, because it was my first time and
because the PERLAPI/PERLGUTS manual doesn't mention or explain a couple
of important items.
I would be very glad if somebody could answer the questions I still have!
(See further below)
(The answers will - no doubt - be also very valuable for anyone trying the
same kind of endeavour)
I'll also include a list of traps I fell into:
1) Users should be warned that if they are trying to build a package
"package.pm" (along with "package.xs"), any file named "package.c"
gets overwritten.
So your C library should have a different name.
The simplest way to include the C library file into the "package.c"
file (that eventually gets compiled into the dynamically linkable
shared library), is to include it in the header of the "package.xs"
file, like this:
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "my_c_lib.c"
The file "my_c_lib.c" should in turn include everything it needs to
get itself compiled.
2) You'll need to supply a file named ".packlist". Use the ".packlist"
files of other extensions as a model.
3) You might need to supply a "typemap" file, for instance in case you
used "typedef"s in your code. You'll find the main typemap file at
the following location:
/..../yourperl5distribution/lib/ExtUtils/typemap
Use this as a model for your own; you will find Perl equivalents for
most of your basic data types.
Now the questions:
1) Suppose the Perl interface of a C function is to be as follows:
($cc,$yy,$mm,$dd) = decode($date);
By how many elements do I need to extend the stack using the EXTEND(sp,num)
macro in this case, if the return values are to be pushed onto the stack
with the PUSHs(SV*) macro? (In detail: "PUSHs(sv_2mortal(newSVnv(cc)));")
By the number of values returned (i.e., EXTEND(sp,4)), or by the number of
values returned MINUS the number of input values, in this case 4 - 1 = 3?
The examples in PERLAPI (for instance, pages 168 middle and 169 bottom)
are not consistent concerning EXTEND(sp,num)! (See also following pages)
2) The PERLGUTS manual fails to specify what has to be supplied as the second
argument to the function
SV* newSVpv(char*, int);
From examples found in the Perl C sources, it seems to me that the length
of the string pointed to by the first argument has to be given, but in
many examples, this value was zero!
Also, it is unclear to me wether the STRING pointed to by the first argu-
ment is COPIED into newly allocated memory (allowing to free() the origi-
nal string), or if the newly created variable only contains a copy of the
POINTER (free()ing the original string would be a bad idea in this case!).
3) I didn't understand the real difference between EXPORT and EXPORT_OK.
Is it possible to call functions of a package without explicitly referen-
cing them, if they are exported by the package by one of the two state-
ments above, and imported by a "use package qw(function1 function2);"
statement in your application?
Like this, for instance:
#!/opt/bin/perl5
use datecalc qw( decode(date) );
...
($cc,$yy,$mm,$dd) = decode($date);
instead of:
($cc,$yy,$mm,$dd) = datecalc::decode($date);
Also, I discovered that I didn't need to declare the functions in the "use"
statement in order to use them (they were exported by the package via the
"EXPORT_OK" statement).
Is this a bug or a feature?
If it's a feature, what do I need the declaration of functions in the "use"
statement for?
My "EXPORT_OK" statement in "datecalc.pm" is:
@EXPORT = qw();
@EXPORT_OK = qw( leap(year) encode(yy,mm,dd) decode(date) valid_date(date)
date_string(date) check_date(year,mm,dd) calc_days(year,mm,dd)
dates_difference(year1,mm1,dd1,year2,mm2,dd2) day_of_week(year,mm,dd)
calc_new_date(year,mm,dd,offset) date_to_short(year,mm,dd)
date_to_string(year,mm,dd) week_number(year,mm,dd) first_in_week(week,year)
weeks_in_year(year) decode_date(buffer) day_short_tab(dd) day_name_tab(dd)
month_short_tab(mm) month_name_tab(mm) );
Maybe there is something wrong with this? (Am I missing something obvious?)
Any help is greatly appreciated (as always ;-) )
and will be highly praised! ;-)
Many thanks in advance,
have fun!
Yours,
--
Steffen Beyer
mailto:sb@sdm.de |s |d &|m | software design & management GmbH&Co.KG
phone: +49 89 63812-244 | | | | Thomas-Dehler-Str. 27
fax: +49 89 63812-150 | | | | 81737 Munich, Germany.
Recently I tried (and eventually succeeded) to include a C library of my own
(for all sorts of date calculations, in agreement with the ISO/R 2015-1971
and DIN 1355 norms) as a (dynamically linked) package into Perl 5.
Unfortunately, it was rather difficult, because it was my first time and
because the PERLAPI/PERLGUTS manual doesn't mention or explain a couple
of important items.
I would be very glad if somebody could answer the questions I still have!
(See further below)
(The answers will - no doubt - be also very valuable for anyone trying the
same kind of endeavour)
I'll also include a list of traps I fell into:
1) Users should be warned that if they are trying to build a package
"package.pm" (along with "package.xs"), any file named "package.c"
gets overwritten.
So your C library should have a different name.
The simplest way to include the C library file into the "package.c"
file (that eventually gets compiled into the dynamically linkable
shared library), is to include it in the header of the "package.xs"
file, like this:
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "my_c_lib.c"
The file "my_c_lib.c" should in turn include everything it needs to
get itself compiled.
2) You'll need to supply a file named ".packlist". Use the ".packlist"
files of other extensions as a model.
3) You might need to supply a "typemap" file, for instance in case you
used "typedef"s in your code. You'll find the main typemap file at
the following location:
/..../yourperl5distribution/lib/ExtUtils/typemap
Use this as a model for your own; you will find Perl equivalents for
most of your basic data types.
Now the questions:
1) Suppose the Perl interface of a C function is to be as follows:
($cc,$yy,$mm,$dd) = decode($date);
By how many elements do I need to extend the stack using the EXTEND(sp,num)
macro in this case, if the return values are to be pushed onto the stack
with the PUSHs(SV*) macro? (In detail: "PUSHs(sv_2mortal(newSVnv(cc)));")
By the number of values returned (i.e., EXTEND(sp,4)), or by the number of
values returned MINUS the number of input values, in this case 4 - 1 = 3?
The examples in PERLAPI (for instance, pages 168 middle and 169 bottom)
are not consistent concerning EXTEND(sp,num)! (See also following pages)
2) The PERLGUTS manual fails to specify what has to be supplied as the second
argument to the function
SV* newSVpv(char*, int);
From examples found in the Perl C sources, it seems to me that the length
of the string pointed to by the first argument has to be given, but in
many examples, this value was zero!
Also, it is unclear to me wether the STRING pointed to by the first argu-
ment is COPIED into newly allocated memory (allowing to free() the origi-
nal string), or if the newly created variable only contains a copy of the
POINTER (free()ing the original string would be a bad idea in this case!).
3) I didn't understand the real difference between EXPORT and EXPORT_OK.
Is it possible to call functions of a package without explicitly referen-
cing them, if they are exported by the package by one of the two state-
ments above, and imported by a "use package qw(function1 function2);"
statement in your application?
Like this, for instance:
#!/opt/bin/perl5
use datecalc qw( decode(date) );
...
($cc,$yy,$mm,$dd) = decode($date);
instead of:
($cc,$yy,$mm,$dd) = datecalc::decode($date);
Also, I discovered that I didn't need to declare the functions in the "use"
statement in order to use them (they were exported by the package via the
"EXPORT_OK" statement).
Is this a bug or a feature?
If it's a feature, what do I need the declaration of functions in the "use"
statement for?
My "EXPORT_OK" statement in "datecalc.pm" is:
@EXPORT = qw();
@EXPORT_OK = qw( leap(year) encode(yy,mm,dd) decode(date) valid_date(date)
date_string(date) check_date(year,mm,dd) calc_days(year,mm,dd)
dates_difference(year1,mm1,dd1,year2,mm2,dd2) day_of_week(year,mm,dd)
calc_new_date(year,mm,dd,offset) date_to_short(year,mm,dd)
date_to_string(year,mm,dd) week_number(year,mm,dd) first_in_week(week,year)
weeks_in_year(year) decode_date(buffer) day_short_tab(dd) day_name_tab(dd)
month_short_tab(mm) month_name_tab(mm) );
Maybe there is something wrong with this? (Am I missing something obvious?)
Any help is greatly appreciated (as always ;-) )
and will be highly praised! ;-)
Many thanks in advance,
have fun!
Yours,
--
Steffen Beyer
mailto:sb@sdm.de |s |d &|m | software design & management GmbH&Co.KG
phone: +49 89 63812-244 | | | | Thomas-Dehler-Str. 27
fax: +49 89 63812-150 | | | | 81737 Munich, Germany.