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使用調試器