如何在C程序中嵌入Perl
1个回答
推荐于2016-05-13 · 知道合伙人数码行家
huanglenzhi
知道合伙人数码行家
向TA提问 私信TA
知道合伙人数码行家
采纳数:117538
获赞数:517179
长期从事计算机组装,维护,网络组建及管理。对计算机硬件、操作系统安装、典型网络设备具有详细认知。
向TA提问 私信TA
关注
展开全部
如果你编译本文档中的脚本有困难。那么你不是一个人在战斗。记住重要原则: 以编译你的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。
% interp print "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.pl 818284590
返回从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的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。
% interp print "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.pl 818284590
返回从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)); ...
这种方法,我们通过不创建全局变量以及简化我们的化码,避免了名字空间污染。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询