
Perl支持对源代码的共享,通用于程序司以存放在文件中,并在程序中进行调用,这 *** 作要通过require语句来实现,其格式如下:
require”cgi-lib.pl”:
它类似丁C语击中的#include预处理。Perl在查找源文件时,首先搜索缺省的库日录,然后搜索当前目录,也可以采用绝对路径指定文件名中的路径信息。
通过require函数的机制,可以把程序分割成多个文件并分别编写,以创建函数库。例如,在filel.pl中自定义好的Perl函数,现需要在file2.pl中使用该函数,可以用语句require(”filel.pl“)将它包含进来。当Perl中解释器执行到这一语句时,就在指定的目录中寻找文件filel.pl,
如果找到则执行文件中的语句,否则程序终止并输出错误信息。
Perl中还支持包的概念。在Perl中,程序把变量和子程序的名称存储到符号表中,这个符号表中的变量和子程序的集合就称为包(package)。在一个程序中可以定义多个包,每个包有一个单独的符号表,它定义的格式为:
package
packname
此语句定义个名为packname的包。在程序中,这个包定义语句以后的所有定义的变量和子程序名字,它们都存储在与该包关联的符号表中,直到遇到下一个package
语句为止。这样定义的好处是,与每个包相关的符号表有其自己的变量、子程序名空间,各个包中的变量是不相关的,因此可以在不同的包中使用相同的变量,而不会发生冲突。
在一个包中可以引用其它包中定义的变量或子程序,办法是在变量名前而加上包名和一个单引号。如:
$packname'var
在Perl中还支持模块,模块就是包含了变量和子程序的程序集合。使用use语句可以将已经存在的模块导入程序中,其格式如下:
use
module:
它导入了module模块,这样在模块module中定义的子程序和变量就可以使用了。取消导入的模块使用no语句,其格式为:
no
mnodule
它将取消module模块的导入。
Perl
5提供了些预定义模块,叫以用use导入并使用,下面是库中常用的一些模块:
Integer
整数运算模块
Diagnostics
诊断信息模块
Env
环境变量模块
POSIX
POSIX标准接口模块
Socket
网络套接字处理模块
如果你编译本文档中的脚本有困难。那么你不是一个人在战斗。记住重要原则: 以编译你的perl的方式,编译你的程序(不好意思)并且,每一个使用了Perl的C程序都必须连接 perl 库. 你问,那是什么?Perl本身就是用C写的。Perl库是编译过的用来创建Perl可执行程序的C程序集合 (/usr/bin/perl或者类似的)。(结论:你不能在没有编译过或者正确安装过Perl的系统中编译嵌入了Perl的C程序。不正确安装指,只是复制了Perl的二进制可执行文件而没有复制perl的库目录。)
当你在C中使用Perl时, 你的C程序将要--通常--需要创建、执行,然后销毁一个 Perl解释器
如果你的Perl烤备足够新到包含本文档 (版本5.002或者更新), 则Perl库 (以及你将需要的EXTERN.h 和 perl.h) 将会在类似这样的目录中:
/usr/local/lib/perl5/your_architecture_here/CORE
或者可能就直接是
/usr/local/lib/perl5/your_architecture_here/CORE
或者可能类似
/usr/opt/perl5/CORE
执行这个表达式可以定位这个目录:
perl -MConfig -e 'print $Config{archlib}'
这是如何编译下节的示例代码:往你的C程序中墙加一个Perl解释器的语句,在我的linux机器上是这样:
% gcc -O2 -Dbool=char -DHAS_BOOL -I/usr/local/include-I/usr/local/lib/perl5/i586-linux/5.003/CORE-I/usr/local/lib/perl5/i586-linux/5.003/CORE-o interp interp.c -lperl -lm
(那些是一行。) 在我跑着老版本perl 5.003_05的DEC Alpha机器上, 有一点点儿不一样:
% cc -O2 -Olimit 2900 -DSTANDARD_C -I/usr/local/include-I/usr/local/lib/perl5/alpha-dec_osf/5.00305/CORE-L/usr/local/lib/perl5/alpha-dec_osf/5.00305/CORE -L/usr/local/lib-D__LANGUAGE_C__ -D_NO_PROTO -o interp interp.c -lperl -lm
你如何找出需要填加什么?如果你的Perl版本高于5.001, 执行 perl -V 命令,注意一下它的有关``cc'' 和 ``ccflags''的信息。
你将不得不根据你的系统选择适当的编译器。 (cc,gcc,等等。) : perl -MConfig -e 'print $Config{cc}' 将告诉你用什么。
你还得根据你的系统选择正确的Perl库目录 (/usr/local/lib/...) 如果你的编译器抱怨有函数未定义,或者它不能定位 -lperl,则你需要用-L手动指定库文件路径。如果它抱怨找不到EXTERN.h 和 perl.h,你需要用-I手动指定头文件路径。
你可能还需要如法增加其它库哪些?可能包括这行指令打印出的这些:
perl -MConfig -e 'print $Config{archlib}'
如果你的perl配置安装无误,则模块ExtUtils::Embed将为你检测出你需要的所有信息。
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
如果ExtUtils::Embed不包含在你的perl发行版中, 你可以从http://www.perl.com/perl/CPAN/modules/by-module/ExtUtils/.下载它 (如果本文档来自你的perl发行版,则你已经安装了perl 5.004或者更高的版本,并且你肯定有这个模块)
CPAN上的ExtUtils::Embed,包括了有关本文档的所有的源码、测试以及其它对你有用的示例程序。
--------------------------------------------------------------------------------
往你的C程序中增加一个Perl解释器
通常, perl (C源程序) 是一个嵌入Perl(语言)的好例子,所以我将示范一个miniperlmain.c。当然,它不太标准,也不太精巧。
#include <EXTERN.h> /* from the Perl distribution */#include <EXTERN.h> /* from the Perl distribution */
static PerlInterpreter *my_perl /***The Perl interpreter***/
int main(int argc, char **argv, char **env){my_perl = perl_alloc() perl_construct(my_perl) perl_parse(my_perl, NULL, argc, argv, (char **)NULL) perl_run(my_perl) perl_destruct(my_perl) perl_free(my_perl) }
注意我们没有使用env指针。通常做为perl_parse的最后一个选项, env参数为NULL,代表使用当前的环境变量。
现在编译它 (我将叫它 interp.c)为可执行文件:
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
经过成功的编译以后, 你将可以像使用perl一样地使用interp。
% interpprint "Pretty Good Perl \n" print "10890 - 9801 is ", 10890 - 9801 <CTRL-D> Pretty Good Perl 10890 - 9801 is 1089
或者
% interp -e 'printf("%x", 3735928559)'deadbeef
你也可以通过在调用perl_fun以前替换argv[1],在C程序里从一个文件中读取然后执行Perl代码。
--------------------------------------------------------------------------------
在你的C程序中调用一个Perl子程序
为了调用独立的Perl子程序,你可以使用任何<al>perlcall手册</al>中的perl_call_*类型的函数。在此例中,我们将使用perl_call_argv。
它们将在下面这个我叫做showtime.c的程序中中展现。
#include <EXTERN.h> #include <perl.h>
static PerlInterpreter *my_perl
int main(int argc, char **argv, char **env){char *args[] = { NULL } my_perl = perl_alloc() perl_construct(my_perl)
perl_parse(my_perl, NULL, argc, argv, (char **)NULL)
/*** skipping perl_run() ***/
perl_call_argv("showtime", G_DISCARD | G_NOARGS, args)
perl_destruct(my_perl) perl_free(my_perl) }
showtime是一个Perl子程序,它没有参数。 (它是 G_NOARGS) 并且我将忽略它的返回值 (它是G_DISCARD). 那些标记,以及其它一些标记,在perlcall手册中。
我将在文件<el>showtime.pl</el>中定义showtime函数:
print "I shan't be printed."
sub showtime {print time }
足够简单。现在编译并运行:
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
% showtime showtime.pl818284590
返回从1970年1月1日 (Unix epoch开始时间)到现在我正在执行程序语句的时间。
在这一部分,我们不需要调用perl_run,但是通常好的编程习惯来保证正确的使用库是好的,包括对所有的对象调用 DESTROY 方法以及块的END {}。
如果你想传递参数给Perl函数,你可以填加以NULL结尾的args表给perl_call_argv。为了其它数据类型或者测试返回值,你将需要 *** 作Perl的栈。那将在本文档最后的章节进行讨论: 在你的C程序中 *** 作Perl的栈。
--------------------------------------------------------------------------------
在你的C程序中执行一个Perl表达式
Perl提供了两个API函数来执行Perl代码片断。它们是perl_eval_sv 和 perl_eval_pv。
经常的情况是,你只需要在程序中执行一块的Perl代码。它可以如你所愿的长:它可以包括 use、require和 do 用来包含其它的外部Perl文件。
perl_eval_pv 可以让我执行单独的Perl语句,然后把执行结果变量返回成C的形式。下面的程序 string.c,执行三个Perl语句, 从第一个取得int,从第二个取回float, 从第三个取回char *。
#include <EXTERN.h> #include <perl.h> static PerlInterpreter *my_perl int main(int argc, char **argv, char **env) { STRLEN n_a char *embedding[] = { "", "-e", "0" } my_perl = perl_alloc() perl_construct(my_perl) perl_parse(my_perl, NULL, 3, embedding, NULL) perl_run(my_perl) /** Treat $a as an integer **/ perl_eval_pv("$a = 3$a **= 2", TRUE) printf("a = %d\n", SvIV(perl_get_sv("a", FALSE))) /** Treat $a as a float **/perl_eval_pv("$a = 3$a **= 2", TRUE) printf("a = %f\n", SvNV(perl_get_sv("a", FALSE))) /** Treat $a as a float **/ perl_eval_pv("$a = 'rekcaH lreP rehtonA tsuJ'$a = reverse($a)", TRUE) printf("a = %s\n", SvPV(perl_get_sv("a", FALSE), n_a)) perl_destruct(my_perl) perl_free(my_perl) }
所有这些名字中含有 sv 的这些怪函数都帮助把Perl的标量返回成C的类型。它们在 perlguts手册里有描述。
如果你编译并运行string.c,你将看到 SvIV()创建整数,SvNV()创建浮点数,以及SvPV()创建一个字符串:
a = 9 a = 9 a = Just Another Perl Hacker
在上例中,我们创建了一个全局的变量来保存我们表达式执行的结果。在很多情形下,通过perl_eval_pv()的执行结果来取回返回值,也不错。如:
... STRLEN n_a SV *val = perl_eval_pv("reverse 'rekcaH lreP rehtonA tsuJ'", TRUE) printf("%s\n", SvPV(val,n_a)) ...
这种方法,我们通过不创建全局变量以及简化我们的化码,避免了名字空间污染。
Perl 最初的设计者为拉里·沃尔(Larry Wall),它于1987年12月18日发表。Perl借取了C、sed、awk、shell scripting以及很多其他程序语言的特性。Larry Wall在新闻组comp.sources.misc发布了Perl脚本语言1.0版,当时他是Unisys公司的一名程序员。Perl借鉴了sh、Awk和Sed等脚本语言的特性,试图成为一个能简化报告处理的通用 Unix脚本语言。Perl 2在1988年发布,增加了更多特性,拥有更好的正则表达式引擎。Perl 3和 Perl 4分别在1989年和1991年发布,而1994年发布的 Perl 5则是最重要的一个版本,至今仍在开发中。2000年启动的Perl 6则完全重写了Perl,基于不同的原则,开发者决定先制定语言规格。Perl 6的发布日期被认为是圣诞节,但没有指定哪一年的圣诞节。Perl 5公布了16个版本,Perl 5.6在2000年发布,Perl 5.8的持续开发贯穿了2002-08年,5.10在2007年发布,5.12在2010年发布,此后 Perl开始采用每月发布一个版本每年发布一个稳定版本的发布周期,5.14在2011年发布,5.16于2012年发布。
Perl 一般被称为“实用报表提取语言”(PracticalExtraction andReportLanguage),虽然有时被称做“病态折中垃圾列表器”(PathologicallyEclectic Rubbish Lister)。它是术语,而不仅仅是简写,Perl的创造者,LarryWall提出第一个,但很快又扩展到第二个。那就是为什么“Perl”没有所有 字母都大写。没必要争论那一个正确,Larry 两个都认可。你也可能看到“perl”,所有的字母都是小写的。一般,“Perl”,有大写的 P,是指语言本身,而“perl”,小写的 p,是指程序运行的解释器。Perl的正式网站是 www.perl.org。
Perl 的特点
Perl的解释程序是开放源码的免费软件,使用Perl不必担心费用,Perl能在绝大多数 *** 作系统运行,可以方便地向不同 *** 作系统迁移。
Perl 是一种能完成任务的语言。从一开始,Perl 就设计成可以把简单工作简单化,同时又不失去处理困难问题能力的语言。它可以很容易 *** 作数字、文本、文件和目录、计算机和网络、特别是程序的语言。这种语言应该很容易运行外部的程序并且扫描这些程序的输出获取感兴趣的东西,而且它还应该很容易能把这些你感兴趣的东西交给其它程序做特殊的处理,当然这种语言还应该很容易在任何现代的 *** 作系统上可以移植地编译和运行。
Perl 基本语法
标量定义,以$号开头,如:$num =1
数组定义,以@开头,如:@array = (1,2,3)
数组元素调用 @array[index],其中index表示数组下标,如上例,@array[0]的值是1
散列定义,以%开头,如:%hash=("a",1,"b",2)
散列调用 %hash,其中key表示键值,如上例,%hash{"b"}的值是1
Perl 的哲学
Perl追求的是简单, 解决一个一般的问题用它几行代码就完成了. 一个稍复杂一点的问题代码也不会超过一屏! 事实上, 大多数人用Perl写的程序大多都没超过100行.
Perl 最初是当做一种 Unix 的胶水语言设计的,但是她早就移植到大多数其它 *** 作系统里了。因为 Perl 几乎可以在任何地方运行,所以 Perl 可以说是当今最具有移植性的编程环境。要想写可移植的 C/C++ 程序,你得在程序里加上一大堆 #ifdef 标签来区分不同的系统。要想写可移植的 Java 程序,你必须理解每种新的 Java 实现的特质。要想写可移植的shell,你可能要记住每条命令在每种 *** 作系统上的语法,走运的时候你可能可以找到一些公共的东西。而要想写可移植的 Visual Basic 程序,那么你只需要对“移植”有个更灵活的定义就可以了。
我们很高兴的是 Perl 避免了所有这些问题,同时还保留了这些语言中的许多优点,同时还有一些自己的特色。Perl 的特色来自许多方面:它的特性集的工具,Perl 社区的创造性,以及开源运动的大环境。不过,许多这些特性都是混合的东西;Perl 的身世复杂,它总是把事物看成是优点的不同方面,而不是弱点。Perl 是“背黑锅我来”的语言。如果你觉得自己陷入一团乱麻之中,非常渴望自由,那么请使用 Perl。
Perl 是跨文化的。Perl 的爆炸性增长很大程度上是因为那些前 Unix 系统程序员的渴望,他们希望从他们的“老家”带着尽可能多的东西。对于他们而言,Perl 是可移植的 Unix 文化蒸馏器,是"此路不通"的沙漠中的绿洲。从另外一个角度来看,Perl 还可以从另外一个方向运转:在 Windows 上工作的 web 设计者通常会非常开心地发现他们的 Perl 程序可以不加修改地在 Unix 服务器上跑。
尽管 Perl 在系统程序员和 web 设计师中间非常流行,但这只是因为是他们最早发现 Perl 的,Perl 可以用于更广泛的用途。从 Perl 最早的文本处理语言开始,它已经发展成为一种非常复杂的,通用的编程语言,以及完整的开发环境,包括调试器、调节器、交叉引用、编译器、库、语法提示编辑器,以及所有其它“真正”的编程语言所具有的所有挂勾,只要你需要。当然这些东西都是让我们可能处理难的问题的东西,而且很多其它语言也可以做到这一点。 Perl 之所以成为 Perl 是因为它从来不会因为保持简单事情简单化而丢失其他方面的特性。
因为 Perl 既强大又好用,所以它被广泛地用于日常生活的方方面面,从宇航工程到分子生物学,从数学到语言学,从图形处理到文档处理,从数据库 *** 作到网络管理。很多人用 Perl 进行快速处理那些很难分析或转换的大批量数据,不管你是处理 DNA 序列、网页、还是猪肚皮的未来都无所谓。实际上,在 Perl社区有一个笑话就是,下次股市大崩盘就很有可能是呢个家伙写的脚本里头有臭虫造成的。(不过,乐观点来看就是,任何还在失业的股票分析师仍然有可以利用的。)
Perl 的成功有许多原因。Perl 早在开源软件的名字出现之前就已经是一个成功的开源项目了。Perl 是自由的,并将永远自由下去。你可以在任何合适的场合使用Perl,只需要遵守一个非常自由的版权就可以了。如果你在从事商业活动并且还想使用 Perl,那么用就是了。你可以把 Perl 嵌入到你写的商业软件中而不需要支付任何费用也没有任何限制。如果你碰上一个Perl社区解决不了的问题,那你也还有最后的一招:源程序本身。Perl 社区不会在“升级”的伪装下租给你它们的商业秘密,而且Perl 社区也不会“停业”,更不会让你孤立无援。
Perl 是自由软件这一点无疑对它是有帮助的。但这一条并不足以解释 Perl 现象,因为许多自由软件包没有能繁荣起来。Perl 不仅自由;而且好玩。人们觉得自己在 Perl 里可以有创造力,因为它们有表达的自由:他们可以选择是为计算机速度优化还是为程序员的速度优化,是冗长还是简洁,是选择可读性还是可维护性,或者选择复用性、移植性、接受性和传授性等等。假如你进入一次模糊的 Perl 比赛,甚至你还可以为模糊性做优化。
Perl 可以给予你所有这些自由,因为它是一门有着分裂人格的语言,Perl 同时是很简单并且很富有的语言。Perl 从其它地方拿来好主意,然后把它们安装到易用的框架里面。对于只是喜欢她的人来说,Perl 是实用抽取和报表语言(Practical Extractoin and Report Language)。对那些热爱她的人而言,她是变态电子垃圾制造者(Pathologically Electric Rubbish Lister)。在少数人眼里,Perl 是毫无意义的重复练习,不过世界需要一点点冗余,精简主义者总是想把事物分隔开,而我们则总是企图把它们合并到一起。
Perl 之所以是简单的语言是有很多原因的。比如你用不着知道什么特殊的指令就可以编译 Perl 程序--只要把它当做批处理或者shell 脚本执行就可以了。Perl 的类型和结构很容易使用和理解。Perl 对你的数据没有任何限制--你的字串和数组可以要多长就多长(只要你有足够的内存),而且它们都会自动增长。Perl 不会强迫你学习新的语法和语意,Perl 改从许多其它你已经熟悉的语言里(比如 C、awk、BASIC 和 Python、英文、希腊语等)借来语法。实际上,任何程序员都可以从书写良好的 Perl 代码段中读懂它的含义。
最重要的是,你不用先学习所有 Perl 的东西就可以开始写有用的程序。你可以写很小的 Perl 程序。你也可以象小孩那样写 Perl 程序,我们保证不会笑话你。或者更准确地说是,我们绝不会笑话小孩做事情的创造性。Perl 里的许多观点都是从自然语言中借来的,其中一条最好的观点就是只要你能把自己的意思表述清楚,那么你就可以使用这些语言的一个子集。Perl 文化可以接受任何熟练程度的成员。我们不会在你背后放个语言警察。如果你的老板不炒你,而且你的 Perl 脚本也能完成工作,那么它就是“正确”的。
尽管 Perl 很简单,但它仍然是一种特性很丰富的语言,如果你想用那些特性的话,那你就要学习一些东西,这也是把难题变简单的学费。虽然你要想把所有 Perl 能做的事情吸收还需要一些时间,但到你需要这些功能的时候你就会非常开心地发现 Perl 已经可以做这些事情了。
由于 Perl 的继承性,就算它只是用做数据归纳语言的时候也有丰富的特性,Perl 一开始就设计成可以浏览文件,扫描大量文本并且生成动态数据以及打印出这些数据的良好格式化的报表。不过,随后 Perl 就开始风行,于是它就成了可以 *** 作文件系统、进程管理、数据库管理、进行 C/S 编程和安全编程、web 信息管理、甚至可以进行面向对象和面向功能的编程的语言。而且这些功能并非只是在 Perl 这边,每种新功能都和其它东西交流得很好,别忘了 Perl 从一开始就是设计成胶水语言的。
而且 Perl 并不仅仅只能黏合它自己的特性。Perl 是设计成可以用模块扩展的语言。你可以用 Perl 快速设计,编写,调试和部署 Perl 应用,并且你还可以在需要的时候很方便地扩展这些应用。你可以在其它语言里嵌入Perl,而且你也可以在 Perl 里嵌入其它语言。通过模块输入机制,你可以把这些外部的扩展当做内置于 Perl 的特性。那些面向对象的外部库在 Perl 内部仍然保持面向对象的特征。
Perl 还在许多其它方面协助你。和严格的每次执行一条命令的命令文件和 shell 脚本不同的是,Perl 先把你的程序快速编译成一种内部格式。和其它任何编译器一样,这个时候还进行各种优化,同时把碰到的任何问题反馈给你。一旦 Perl 的编译器前端对你的程序表示满意了,它就把这些中间代码交给解释器执行(或者是给其它的能生成C或者字节码的模块后端)。听起来挺复杂,不过 Perl 的编译器和解释器干这些活效率相当高,我们的编译-运行-修改的过程几乎都是以秒计。再加上 Perl 的许多其他开发特性,这种快速的角色转换很适合做快速原型设计。然后随着你的程序的成熟,你可以逐步拧紧身上的螺母,减少散漫增强记律。如果你做得好,Perl 也能帮你这个忙。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)