1. 加急! 如何将c语言嵌入perl中
有些应用中perl的速度比较慢,但是如果和c结合起来,就可以解决这样的问题了。perl和c结合有三种办法,第一是用c来写xs制作perl模块,再在perl代码中加载,这个比较简单,CU和IBM都有文档看,我就不写了。第二是在C中嵌入perl脚本,这个对我来说没什么用,我还没看。第三就是本文要说的,在Perl中嵌入C代码了。实现起来简单方便,唯一的要求是运行perl脚本的机器要有编译器,VC和GCC都行。直接看代码吧,然后再解释:
代码:
#!/usr/bin/perl
use warnings;
use strict;
use Inline C => <<'END_C';
#include <windows.h>
SV *MakeSV( char *name )
{
return newSVpvf( "I'm %s", name );
}
HV *MakeHash( char *key_name, char *value )
{
HV *my_hash = newHV( );
hv_store( my_hash, key_name, strlen(key_name), newSVpv( value, strlen(value) ), 0 );
return my_hash;
}
void AddKey( HV *my_hash, char *key_name, char *value )
{
hv_store( my_hash, key_name, strlen(key_name), newSVpv( value, strlen(value) ), 0 );
}
void MyBox( char *title, char *content )
{
MessageBox( NULL, content, title, MB_OKCANCEL );
}
END_C
print MakeSV( "yunshu\n" );
my %hash = %{ MakeHash( "first", "yunshu" ) };
$hash = "icy";
AddKey( \%hash, "third", "nmap" );
AddKey( \%hash, "end", "luoluo" );
foreach my $key( keys(%hash) )
{
print "$key\t->\t".$hash."\n";
}
MyBox( "test", "hello world" );
首先是use Inline C => <<'END_C';引入模块表示要嵌入C语言代码,并且指名END_C表示C代码结束。这里的C代码中,MakeSV函数我演示了如何将C 中的字符串返回给Perl成为标量;MakeHash函数,我演示了如何创建一个哈希表(HashTable),并保存了一个key和它的value,然后将这个哈希表返回给Perl使用;AddKey函数,我演示了如何在Perl中使用C中返回的哈希表,并用C代码添加一个元素;MyBox函数,我演示了如何调用windows的API函数。代码很简单,看看就明白了。
需要注意的是,当C代码中需要指针的时候,你必须在Perl中传递一个应用给C函数;当C中返回一个指针的时候,你需要使用%{ }将C中返回的HashTable指针(引用)转换成HashTable,转换数组则使用@{ }来进行。这里C代码中的一些函数,都是Perl提供的C API接口,详细的资料可以参考:http://perldoc.perl.org/perlguts.html,你安装perl的目录下面有离线版本。
2. perl在windows下如何运行
1. 先检查你的perl是否在系统的PATH环境变量中:
开始->运行,输入cmd,然后运行 perl -v,如果能显示perl的版本,说明你的perl已经在PATH环境变量中;如果显示“不是内部命令也不是外部命令”,那参照以下流程把perl加入PATH环境变量:
右键单击我的电脑,选择“属性”,点击“高级选项卡”,单击“环境变量”,在“系统变量”下面去找PATH,然后选中它,单击“编辑”,在“变量值”里把perl的安装路径下的bin目录追加到末尾(比如你的perl装在C:\perl,就是C:\perl\bin),然后一路点击确定,就修改好了。再照着上面的方法,验证一下是否添加成功。注意,要在修改完了之后重新打开一个命令行窗口,要不然看不到修改的结果。通常命令行的窗口(cmd那个黑色的窗口)在启动的时候会初始化那些环境变量。
2. 关于perl运行
你看到perl文件(.pl)已经关联到perl解释器上了(就是一个黑色的像帽子样的图标),但是不能直接用双击去执行他,因为如果双击执行,在程序结束之后,perl解释器页退出了,你就看不到结果(就是你说的那个黑色窗口一晃),通常来说,执行perl脚本都是单独打开一个命令行窗口,然后执行:
perl script.pl
来运行,前提是perl加到PATH环境变量里面去了。
如果你的pl文件关联到perl解释器上了,有个偷懒的做法就是直接在命令行下执行:
script.pl
这样Window会自动启动相关联的程序(这里是perl解释器)来打开这个文件,你的perl程序就被执行了!
3. 如何把perl的程序编译成可执行文件
如果在Windows下可以使用perl2exe(找破解版),建议使用PERLAPP(也就是ActivePERL的PDK套件),功能非常强大,不过是商业软件,也可以去找一个破解版本(最新版是5.3XXX). PDK可以把PERL脚本编译成常规应用程序/WINDOWS SERVICE/工具栏程序等等
4. 如何在C程序中嵌入Perl
如果你编译本文档中的脚本有困难。那么你不是一个人在战斗。记住重要原则: 以编译你的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/moles/by-mole/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)); ...
这种方法,我们通过不创建全局变量以及简化我们的化码,避免了名字空间污染。
5. 如何在WINDOWS命令行下运行perl脚本
Linux下perl文件的执行#! /usr/bin/perl
第一个“#”表示是这一行是注释
第二个“!”表示这一行不是普通注释,而是解释器路径的声明行
后面的“/usr/bin/perl”是perl解释器的安装路径,也有可能是:“/usr/local/bin/perl”,如果那个不行,就换这个。
这样修改后,文件就是这个模样:
#!/usr/bin/perl
#test.pl
print "test message! \n";
然后,给文件加上可执行的属性:
$ chmod 755 test.pl 或者 $ chmod +x test.pl
这两个命令用哪一个都可以。
现在执行吧: $ ./test.pl
6. 要学习perl语言,下载了一个perlactive,安装之后这样,怎么使用运行那个在哪写代码跑代码
这个是PDK,简单来说是将perl编译成exe文件用的,事实上perl是解释性语言(脚本语言),正常运行不需要编译成可执行程序。你应该下载ActivePerl,地址是:
http://www.activestate.com/activeperl
7. 怎么在WINDOWS命令行下运行perl脚本
1、先在命令行下输入path,检查C:\strawberry\perl\bin是否在其中。
2、如果是就ok了,要运行perl程序test.pl只需输入perl test.pl即可。
3、如果路径中有空格,要用引号引起来。
8. 请问怎样perl程序文件编译成可执行文件
于是就有此问。答案:在Linux下可以使用PerlCC(本身就随着PERL有的),他是把PERL转换成C语言,然后编译它。
如果在Windows下可以使用perl2exe(找破解版),建议使用PERLAPP(也就是ActivePERL的PDK套件),功能非常强大,不过是商业软件,也可以去找一个破解版本(最新版是5.3XXX).
PDK可以把PERL脚本编译成常规应用程序/WINDOWS SERVICE/工具栏程序等等.功能非常强大.也就是说你利用PERL编写的脚本,在Windows上面做一服务程序,完全没有问题.
9. 我安装strawberry perl但是不知道如何下手开始编写运行perl脚本,求帮助
随便在一个文本文件里面写一个perl程序,在dos几面下面运行下试试。
或者在dos界面下运行perl -v命令,看看是否安装好了。
10. 如何调试perl脚本
进入退出:
perl
-d debugtest用调试器载入perl程序运行,交互式界面
Loading
DB routines from perl5db.pl version 1.3
Editor
support available.
Enter
h or `h h' for help, or `perldoc
perldebug'
for more help.
main::(p4.pl:2): my($xx,$yy)=(1,1);
DB<1>
先是欢迎信息,显示第一个可执行行:程序将要执行的当前行号。包名,文件名,文件中的行号。
提示符DB<n>
n为命令行号。h可看帮助,q退出调试器
l
缺省显示10行 再输入l接着显示10行
l
10 指定显示第10行
l
8-10 指定显示行的范围
l
8+3 指定从哪行开始多少行。
l
subs 指定显示函数,提供函数名。如果太长只显示前几行,用l接着显示
-
显示在当前行前面的行,再输入-继续向前
w
7 包含指定行的显示窗口 windows可能不一样
//
?? 从当前行搜索包含指定模式的行 /find/
//从前向后正向搜索,??从后向前逆向搜索 可忽略?? //中后面的? /。
S
列出所有函数,包名::函数
无参数的缺省形式列出所有底层和继承的函数,太多。加上搜索模式,指定当前程序包 S main可列出含main的函数
s 执行单条语句 显示下一条要执行的语句。如果需要交互会等待输入。
对于函数,仅仅是进入不执行,如果不进入函数内部,要跳过用n。不能进入系统内部的库函数,只能进入自己定义的
n 执行一行程序,stepover 不进入函数。
f 执行当前函数剩下的语句,显示跟随函数的语句
step
out 旧命令,现在为切换文件名
回车
如果执行了s或n,以后只用回车重复执行上一个s或n的命令。
r 在函数中执行到函数外
b 10
在哪一行设置断点。如果此行非执行语句,显示不能设置断点。如果一条语句有多行,则在第一行设置,其余行不能设置。
b func在函数处设置断点
b 10
($curdir eq
"") 当条件为真时中断执行
c
执行到断点或终止。继续
c
12临时断点,只中断一次,继续执行在12行中断。
L
列出所有断点。列出前几行,当前行,断点。断点条件。
B
10删除断点。不带参数认为是下一行是断点。
B *
删除所有断点。
X
var 不带参数列出main包的所有变量,包括预定义的变量。指定变量不带$,@。可能是符号表中的变量才行。现在与V同。
V
var 列出任何包的变量。只指定包名列出包的所有变量。指定包及变量为main
var。无::
S
列出所有可用的函数,包名::函数 无参数的缺省形式列出所有底层和继承的函数,太多。加上搜索模式,
指定当前程序包
S
main可列出含main的函数
p
expr
指印表达式值。把标准输出重定向也会输出到屏幕。
程序到达某一行时指定执行一条或多条语句。常见的行动作是显示变量值或把含错误值的变量重置为指定的值
a
10 print ("curdir is $curdir\n") 多条语句在一行中用分号;分开,当要续行时用\ 执行完第10行执行指定的语句。
A
*删除所有行动作
A 10删除第10行的动作
>
print 在程序开始执行前执行语句。无参数形式删除设置
<
print 在程序执行完成后执行语句。无参数形式删除设置
跟踪 显示每一个执行行。
t
打开,关闭跟踪。每执行显示一行。
任何非调试命令的perl语句都可执行。分号可忽略。更改变量值。
H
列出从前命令
!
n 执行从前命令。忽略行号执行上一条命令
n=-2跳过2条命令。从当前H列表逆向跳过。
T
栈跟踪。调用级
$
= &main::sub2('hi') from file debug1 line 7
$
= &main::sub1('hi') from file debug1 line 3
当前程序在第7行,在main包的sub2函数中,以hi为实际传递的参数。返回简单变量,此函数由sub1调用。
=
别名 命令 给命令定义别名 =
pc print ("curdir is $curdir\n");别名存在%DB(%DB::alias)中。无参数列出定义的别名。输入pc打印语句。
预定义别名:每次加载调试器自动定义别名。在.perldb中加入$DB'alias{"pc"} = 's/^pc/print
("curdir is $curdir\n");/';
错误检查
Lint perl -MO=Lint,-u pl 编译时检查
perldiag错误信息
-w 重定义函数变量未使用
Use strict;
use diagnostics 警告信息。
命令行参数简介
-c 语法检查
-v版本
-w警告信息
-e执行单行程序
-s为程序提供命令行选项。perl -s prog.pl
-q =>$q=1作为选项。不出现在@ARGV中。否则不加-s,-q作为字符串存在@ARGV中。可赋值-abc="abc"
跟在程序名后带-的是选项,不带-的不是,不是选项的项后面的所有都不是选项。
-P先运行c预处理器,输出再由perl执行
-I指定目录中的包含文件
-n循环处理多个文件。不用while
-p读文件行并显示。同n,不用print自动显示。
-i编辑文件,读然后写回文件。
-a分割行到@F
-F分割模式,指定分割符
-0
指定输入行结束符,用八进制表示
-1
指定输出行结束符
-x从消息中抽取程序。忽略行,直到遇到#!..perl。到文件尾,ctrl-d
ctrl-z __END__时结束
-u产生coremp
-U可以执行不安全操作
-S从路径中查找程序
-D设置调试标志
-T写安全程序。从外部获得的数据不能作为命令或修改文件系统
-d使用调试器