これは、Ubuntuオンライン、Fedoraオンライン、Windowsオンラインエミュレータ、MAC OSオンラインエミュレータなどの複数の無料オンラインワークステーションのいずれかを使用して、OnWorks無料ホスティングプロバイダーで実行できるコマンドperlembedです。
プログラム:
NAME
perlembed-Cプログラムにperlを埋め込む方法
DESCRIPTION
前文
あなたは__したいですか:
C from Perl?
perlxstut、perlxs、h2xs、perlguts、および perlapi を読み取ります。
a Unixの プログラム from Perl?
perlfunc でバッククォートと「system」および「exec」について読んでください。
パール from Perl?
perlfuncの「do」とperlfuncの「eval」とperlfuncの「require」について読んでください。
perlfunc の「use」。
C from C?
デザインを再考してください。
パール from C?
読む...
ロードマップ
· Cプログラムのコンパイル
· CプログラムにPerlインタープリタを追加する
· CプログラムからPerlサブルーチンを呼び出す
· CプログラムからPerl文を評価する
· CプログラムからPerlのパターンマッチと置換を実行する
· CプログラムからPerlスタックを操作する
· 永続的な通訳者の維持
· 複数のインタープリタインスタンスの維持
· Cライブラリを使用するPerlモジュールをCプログラムから使用する
· Win32 での Perl の埋め込み
コンパイル C プログラム
このドキュメントのスクリプトをコンパイルする際に問題が発生する場合は、あなただけではありません。
基本的なルール: Perl をコンパイルしたのとまったく同じ方法でプログラムをコンパイルします。
(大声ですみません)
また、Perlを使用するすべてのCプログラムは、 パール ライブラリ。それって何ですか?
Perl自体はCで書かれており、PerlライブラリはコンパイルされたCプログラムの集合である。
Perl実行ファイルを作成するために使用されたもの(/ usr / bin / perl または同等のもの)。(結果:
Perlがマシン上でコンパイルされていない限り、CプログラムからPerlを使用することはできません。
正しくインストールする必要があります。そのため、Perl実行ファイルをマシンから安易にコピーしないでください。
コピーせずに機械に リブ ディレクトリ。)
CからPerlを使う場合、Cプログラムは、通常、メモリを割り当て、実行し、解放します。
Perlインタープリタ Perl ライブラリによって定義されたオブジェクト。
Perlのコピーがこのドキュメントを収録できるほど新しい場合(バージョン5.002以降)は、
後で)、次にPerlライブラリ(そして 外部.h perl.h(これも必要になります)は
次のようなディレクトリに存在します。
/usr/local/lib/perl5/your_architecture_here/CORE
あるいは単に
/usr/local/lib/perl5/CORE
あるいは、
/usr/opt/perl5/CORE
CORE がどこにあるかについてのヒントを得るには、次のステートメントを実行します。
perl -MConfig -e '$Config{archlib} を印刷'
次のセクション「Perlインタープリタを追加する」の例をコンパイルする方法は次のとおりです。
私の Linux ボックスで「C プログラム」を実行すると、次のようになります。
% gcc -O2 -Dbool=char -DHAS_BOOL -I/usr/local/include
-I/usr/local/lib/perl5/i586-linux/5.003/CORE
-L/usr/local/lib/perl5/i586-linux/5.003/CORE
-o interp interp.c -lperl -lm
(これはすべて5.003行です。)私のDEC Alphaでは、古い05_XNUMXが動作しており、呪文は少し
異なる:
% 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の、et al.) をお使いのマシンに合わせてインストールしてください: "perl
-MConfig -e 'print $Config{cc}'" を実行すると、何を使用するかがわかります。
また、適切なライブラリディレクトリを選択する必要があります(/usr/local/lib/...)あなたの
マシン。コンパイラが特定の関数が未定義であると報告したり、
見つけられない -lperlの場合、「-L」に続くパスを変更する必要があります。
見つからない 外部.h perl.h、「-I」に続くパスを変更する必要があります。
追加のライブラリも追加する必要があるかもしれません。具体的には、
perl -MConfig -e '$Config{libs} を印刷'
Perlバイナリが適切に設定され、インストールされている場合、 ExtUtils :: Embed モジュール
これらすべての情報を決定します:
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
Status ExtUtils :: Embed モジュールがPerlディストリビューションの一部でない場合は、取得することができます
from http://www.perl.com/perl/CPAN/modules/by-module/ExtUtils/ (この文書が
Perl ディストリビューションから 5.004 以上を実行している場合は、既にインストールされています。
当学校区の ExtUtils :: Embed CPANのキットには、この例のすべてのソースコードも含まれています。
ドキュメント、テスト、追加の例、その他役立つと思われる情報。
追加 a パール 通訳 〜へ C プログラム
ある意味、Perl(Cプログラム)はPerl(言語)を埋め込む良い例なので、
埋め込みのデモをします ミニパールメイン.cソース配布に含まれています。
これは、ポータブルではない、劣化版です ミニパールメイン.c の必需品を含む
埋め込み:
#含む/* Perlディストリビューションから */
#含む/* Perlディストリビューションから */
static PerlInterpreter *my_perl; /*** Perlインタープリタ ***/
int main(int argc, char **argv, char **env)
{
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_parse(my_perl, NULL, argc, argv, (char **)NULL);
perl_run(my_perl);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
「env」ポインタを使用していないことに注意してください。通常は「perl_parse」の最終引数として渡されます。
引数「env」は「NULL」に置き換えられ、現在の環境が
利用される。
マクロ PERL_SYS_INIT3() PERL_SYS_TERM() Cのシステム固有の調整を提供する
Perlインタープリタを実行するために必要なランタイム環境。一度だけ呼び出されるべきである。
インタープリターをいくつ作成または破棄しても、 PERL_SYS_INIT3()
最初のインタープリターを作成し、 PERL_SYS_TERM() 最後の
通訳。
Since PERL_SYS_INIT3() 「env」を変更する可能性があるので、「env」を
への議論 perl_parse().
また、どのような引数を渡しても、 perl_parse(), PERL_SYS_INIT3() しなければなりません
Cで呼び出される メイン() argc、argv、env を 1 回だけ実行します。
このプログラムをコンパイルします(これを インタープリタ) を実行可能ファイルに変換します。
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
コンパイルが成功すると、 インタープ perl 自体と同様です:
% インタープリテーション
print "Pretty Good Perl \n";
印刷 "10890 - 9801 は "、10890 - 9801;
かなり良いPerl
10890 - 9801は1089です
or
% interp -e 'printf("%x", 3735928559)'
デッドビーフ
C言語で作業中にファイルからPerl文を読み込んで実行することもできます。
プログラムでは、ファイル名を argv [1] 電話する前に perl_run.
呼び出し a パール サブルーチン from C プログラム
個々のPerlサブルーチンを呼び出すには、次のいずれかを使用します。 電話_* 関数は
この例では「call_argv」を使用します。
これは私が呼ぶプログラムで以下に示すものです ショータイム.c.
#含む
#含む
静的 Perl インタープリター *my_perl;
int main(int argc, char **argv, char **env)
{
char *args[] = { NULL };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, argc, argv, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
/*** perl_run() をスキップ ***/
call_argv("showtime", G_DISCARD | G_NOARGS, args);
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
コラボレー ショータイム は引数を取らないPerlのサブルーチンです( G_NOARGS)と
戻り値は無視します(つまり G_DISCARD)。これらの旗やその他の旗は
perlcall で議論されました。
私は定義します ショータイム というファイル内のサブルーチン ショータイム:
print "印刷されません。";
サブショータイム{
印刷時間;
}
とても簡単です。コンパイルして実行してみましょう。
% cc -o showtime showtime.c \
`perl -MExtUtils::Embed -e ccopts -e ldopts`
% ショータイム showtime.pl
818284590
1年1970月XNUMX日(
(Unix 時代)そしてこの文章を書き始めた瞬間です。
この特定のケースでは、 perl_runPL_exit_flagを設定すると
PERL_EXIT_DESTRUCT_END は perl_destruct 内の END ブロックを実行します。
Perlサブルーチンに引数を渡したい場合は、
「NULL」で終了する「args」リストが渡される call_argv他のデータタイプ、または
戻り値を取得するには、Perlスタックを操作する必要があります。これは「いじくり回す」で説明されています。
「C プログラムの Perl スタックを使用します」。
評価する a パール ステートメント from C プログラム
PerlはPerlコードを評価する2つのAPI関数を提供しています。これらは「eval_sv」です。
perlapi と perlapi の「eval_pv」。
おそらく、これらはPerlコードのスニペットを実行するために必要な唯一のルーチンです。
Cプログラム内から。コードは好きなだけ長くでき、複数の
ステートメント; perlfuncの「use」、perlfuncの「require」、perlfuncの「do」を使用できます。
外部の Perl ファイルをインクルードします。
評価pv 個々のPerl文字列を評価し、強制的に変数を抽出します
Cの型に変換します。次のプログラムは、 文字列.cは3つのPerl文字列を実行し、
1 番目からは「int」、2 番目からは「float」、3 番目からは「char *」です。
#含む
#含む
静的 Perl インタープリター *my_perl;
main (int argc, char **argv, char **env)
{
char *埋め込み[] = { "", "-e", "0" };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct( my_perl );
perl_parse(my_perl, NULL, 3, 埋め込み, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
/** $aを整数として扱う **/
eval_pv("$a = 3; $a **= 2", TRUE);
printf("a = %d\n", SvIV(get_sv("a", 0)));
/** $a を float として扱う **/
eval_pv("$a = 3.14; $a **= 2", TRUE);
printf("a = %f\n", SvNV(get_sv("a", 0)));
/** $a を文字列として扱う **/
評価pv(
"$a = 'rekcaH lreP rehtonA tsuJ'; $a = reverse($a);", TRUE);
printf("a = %s\n", SvPV_nolen(get_sv("a", 0)));
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
これらの奇妙な機能はすべて sv 名前にPerlのスカラーをCに変換するのに役立つ
型。perlguts と perlapi で説明されています。
コンパイルして実行すると 文字列.cを使用すると、 SvIV() 作成します
「int」、 SvNV() 「フロート」を作成し、 SvPV() 文字列を作成するには:
a = 9
a = 9.859600
a = 単なる Perl ハッカー
上記の例では、計算結果を一時的に保存するためのグローバル変数を作成しました。
評価された式の値。これは可能であり、多くの場合、より良い戦略である。
戻り値を取得する eval_pv() 代わりに。例:
...
SV *val = eval_pv("reverse 'rekcaH lreP rehtonA tsuJ'", TRUE);
printf("%s\n", SvPV_nolen(val));
...
この方法では、グローバル変数を作成しないことで名前空間の汚染を回避し、
コードも簡素化されました。
パフォーミング パール パターン マッチ 置換 from C プログラム
当学校区の eval_sv() 関数はPerlコードの文字列を評価できるので、
一致と置換を「特化」するためにこれを使用する関数: マッチ(), 代わりの(),
マッチ().
I32 マッチ(SV *文字列、文字 *パターン);
文字列とパターン(例えば、Cプログラムでは「m/clasp/」や「/\b\w*\b/」)が与えられ、
「/\\b\\w*\\b/」のように表示される可能性があります)。 マッチ() 文字列がパターンに一致する場合は1を返し、一致しない場合は0を返します。
さもないと。
int 置換(SV **文字列、char *パターン);
「SV」へのポインタと「=~」演算(例えば「s/bob/robert/g」または
"tr[AZ][az]"), 代わりの() 「SV」内の文字列を次のように変更します。
置換された回数を返す操作。
SSize_t は一致します(SV *文字列、char *パターン、AV **一致);
「SV」、パターン、空の「AV」へのポインタが与えられれば、 マッチ() "$string =~を評価します
リストコンテキストで$pattern"を入力し、 マッチ 配列要素を使用して、
見つかった一致の数。
サンプルプログラムはこちらです。 マッチ.c、3 つすべてを使用します (長い行はここで折り返されています)。
#含む
#含む
静的 Perl インタープリター *my_perl;
/** my_eval_sv(コード、エラーチェック)
** eval_sv() のようなもの
** しかし戻り値はスタックからポップされます
** /
SV* my_eval_sv(SV *sv, I32 エラー発生時にエラーを発生)
{
dSP;
SV* 戻り値;
PUSHMARK(SP);
eval_sv(sv, G_SCALAR);
スパガイン;
retval = POPs;
戻す;
(croak_on_error && SvTRUE(ERRSV)) の場合
croak(SvPVx_nolen(ERRSV));
retval を返します。
}
/** マッチ(文字列、パターン)
**
** スカラーコンテキストでの一致に使用されます。
**
** 一致が成功した場合は 1 を返し、それ以外の場合は 0 を返します。
** /
I32 マッチ(SV *文字列, 文字 *パターン)
{
SV *コマンド = 新しいSV(0)、*戻り値;
sv_setpvf(コマンド、「私の$文字列 = '%s'; $文字列 =~ %s」、
SvPV_nolen(文字列、パターン);
retval = my_eval_sv(コマンド、TRUE);
SvREFCNT_dec(コマンド);
SvIV(retval) を返します。
}
/** 置換(文字列、パターン)
**
** =~ 演算に使用される
** 左側を変更する (s/// と tr///)
**
** 成功した一致の数を返し、
** 入力文字列があればそれを変更します。
** /
I32 置換(SV **文字列、文字 *パターン)
{
SV *コマンド = 新しいSV(0)、*戻り値;
sv_setpvf(コマンド、"$string = '%s'; ($string =~ %s)",
SvPV_nolen(*文字列), パターン);
retval = my_eval_sv(コマンド、TRUE);
SvREFCNT_dec(コマンド);
*文字列 = get_sv("文字列", 0);
SvIV(retval) を返します。
}
/** 一致(文字列、パターン、一致)
**
** リストコンテキストでの一致に使用されます。
**
** 一致した数を返します。
** 一致する部分文字列を **matches に入力します
** /
SSize_t マッチ(SV *文字列, char *パターン, AV **マッチリスト)
{
SV *コマンド = 新しいSV(0);
SSize_t 一致数;
sv_setpvf(コマンド、「私の$文字列 = '%s'; @配列 = ($文字列 =~ %s)」、
SvPV_nolen(文字列、パターン);
my_eval_sv(コマンド、TRUE);
SvREFCNT_dec(コマンド);
*match_list = get_av("配列", 0);
num_matches = av_top_index(*match_list) + 1;
num_matches を返します。
}
main (int argc, char **argv, char **env)
{
char *埋め込み[] = { "", "-e", "0" };
AV *一致リスト;
I32 一致数、i;
SV *テキスト;
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, 3, 埋め込み, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
テキスト= 新しいSV(0);
sv_setpv(text, "彼がコンビニにいるとき、"
「請求書は76セントくらいの金額で、メイナードは」
「彼は何かをすべきだと自覚している、何か」
「そうすれば25セントを取り戻すことができるが、彼は」
「何が何だか分からない」彼は赤いスクイーズを手探りで操作する
「財布を替えて、少年に3ペニーの小銭を渡す」
「彼は正しい運に恵まれることを期待して、ドルを賭けた」
「金額。少年は自分のペニー2枚を返す」
「そして、彼の賞品である大きな輝く25セント硬貨。」
"-RICHH");
if (match(text, "m/quarter/")) /** テキストに 'quarter' が含まれていますか? **/
printf("一致: テキストに「quarter」という単語が含まれています。\n\n");
ほかに
printf("一致: テキストに「quarter」という単語が含まれていません。\n\n");
if (match(text, "m/eighth/")) /** テキストに 'eighth' が含まれていますか? **/
printf("一致: テキストに「eighth」という単語が含まれています。\n\n");
ほかに
printf("一致: テキストに「eighth」という単語が含まれていません。\n\n");
/** /wi../ のすべての出現に一致します **/
num_matches = matches(テキスト、 "m/(wi..)/g"、&match_list);
printf("一致: m/(wi..)/g で %d 件の一致が見つかりました...\n", num_matches);
(i = 0; i < num_matches; i++) の場合
printf("一致: %s\n",
SvPV_nolen(*av_fetch(match_list, i, FALSE)));
printf("\n");
/** テキストからすべての母音を削除します **/
num_matches = replace(&text, "s/[aeiou]//gi");
if (num_matches) {
printf("substitute: s/[aeiou]//gi...%lu 回の置換が行われました。\n",
(符号なしlong)num_matches);
printf("現在のテキストは: %s\n\n", SvPV_nolen(text));
}
/** 置換を試みる **/
if (!substitute(&text, "s/Perl/C/")) {
printf("substitute: s/Perl/C...置換は行われません。\n\n");
}
SvREFCNT_dec(テキスト);
PL_perl_destruct_level = 1;
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
出力を生成します(ここでも長い行は折り返されています)
一致: テキストに「quarter」という単語が含まれています。
一致: テキストに「eighth」という単語が含まれていません。
一致: m/(wi..)/g 2 件の一致が見つかりました...
一致:
一致: と
交代: s/[aeiou]//gi...139回の交代が行われました。
現在のテキストは次のとおりです: Whn hst cnvnnc str nd th bll cms t sm mnt lk 76 cnts,
Mynrd は thr s smthng h *shld* d、smthng tht wll nbl hm t gt を見て
バッククォーター、バットハンマーと*wht*。ハンマーを通してスクイジーチェンジとハンマーを振る。
gvs th by thr xtr pnns with hs dllr, hpng thh h mgh lck nt th crrct
山Th by gvs hm bck tw f hs wn pnns nd thn th bg shny qrtr tht s
hs prz. -RCHH
代替: s/Perl/C...代替は行われません。
いじくり回す パール スタック from C プログラム
スタックを説明しようとすると、ほとんどのコンピュータサイエンスの教科書では、
バネ仕掛けのカフェテリアの皿の列:最後に積み重ねたものは
最初にポップオフするもの。これで十分です。Cプログラムはいくつかのものをプッシュします
引数を「Perlスタック」に投入し、魔法が起こるまで目を閉じ、その後
結果 (Perl サブルーチンの戻り値) をスタックから取得します。
まず、Cの型とPerlの型を変換する方法を知る必要があります。 newSViv()
sv_setnv() 新しいAV() そしてその仲間たち。それらはペルガットで説明されており、
perlapi。
次に、Perlスタックの操作方法を知る必要があります。これはperlcallで説明されています。
これらを理解すれば、C に Perl を埋め込むのは簡単です。
Cには整数の累乗の組み込み関数がないので、Perlの**
演算子が利用可能です(これは思ったほど便利ではありません。Perlは**を実装しているからです。
C付き 捕虜() 関数)。まずスタブのべき乗関数を作成します。 パワー.pl:
サブエキスポ{
my($ a、$ b)= @_;
$a ** $b を返します。
}
ではCプログラムを作りましょう。 パワー.c、機能付き PerlPower() すべてを含む
2つの引数をプッシュするために必要なperlguts エクスポ() 戻り値をポップします。
深呼吸しましょう...
#含む
#含む
静的 Perl インタープリター *my_perl;
静的ボイド
PerlPower(int a, int b)
{
dSP; /* スタックポインタを初期化する */
ENTER; /* ここから後に作成されるものすべて */
SAVETMPS; /* ...は一時変数です。 */
PUSHMARK(SP); /* スタックポインタを記憶する */
XPUSHs(sv_2mortal(newSViv(a))); /* ベースをスタックにプッシュする */
XPUSHs(sv_2mortal(newSViv(b))); /* 指数をスタックにプッシュする */
PUTBACK; /* ローカルスタックポインタをグローバルにする */
call_pv("expo", G_SCALAR); /* 関数を呼び出す */
SPAGAIN; /* スタックポインタを更新 */
/* スタックから戻り値をポップする */
printf ("%d の %d 乗は %d です。\n", a, b, POPi);
戻す;
FREETMPS; /* 戻り値を解放する */
LEAVE; /* ...そして XPUSH された「モータル」引数。*/
}
int main (int argc, char **argv, char **env)
{
char *my_argv[] = { "", "power.pl" };
PERL_SYS_INIT3(&argc,&argv,&env);
my_perl = perl_alloc();
perl_construct( my_perl );
perl_parse(my_perl, NULL, 2, my_argv, (char **)NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
perl_run(my_perl);
PerlPower(3, 4); /*** 3 ** 4 を計算 ***/
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
}
コンパイルして実行します:
% cc -o power power.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
% 力
3の4乗は81です。
保守 a 永続性 通訳
インタラクティブなアプリケーションや長時間実行される可能性のあるアプリケーションを開発する場合は、
新しいインタープリタを割り当てて構築するのではなく、永続的なインタープリタを維持する
インタープリタを複数回実行します。主な理由は速度です。Perlは
一度メモリに保存します。
しかし、名前空間と変数のスコープについては、より慎重に使用する必要があります。
永続インタープリタ。これまでの例では、
デフォルトパッケージ「main」。実行されるコードを正確に把握していたので、
変数の衝突とシンボル テーブルの過度な増加を回避します。
アプリケーションが、時々Perlコードを実行するサーバーだとしましょう。
任意のファイルです。サーバー側は、どのコードが実行されるかを知る術がありません。非常に
危険な。
ファイルが「perl_parse()」によって取り込まれ、新しく構築されたインタープリタにコンパイルされた場合、
その後「perl_destruct()」で消去すれば、ほとんどの
名前空間の問題。
このシナリオで名前空間の衝突を避ける一つの方法は、ファイル名を
保証された一意のパッケージ名を使用し、その後「eval」を使用してそのパッケージにコードをコンパイルします。
perlfuncで。以下の例では、各ファイルは一度だけコンパイルされます。または、
アプリケーションは、ファイルに関連付けられたシンボルテーブルを消去することを選択する場合があります。
もう必要ありません。perlapiの「call_argv」を使って、サブルーチンを呼び出します。
「Embed::Persistent::eval_file」は「persistent.pl」ファイル内に存在し、
ファイル名とブール値のクリーンアップ/キャッシュ フラグを引数として指定します。
プロセスは使用するファイルごとにサイズが大きくなることに注意してください。さらに、
「AUTOLOAD」されたサブルーチンや、Perlのシンボルが
テーブルが大きくなると、プロセスのサイズを追跡するロジックを追加したり、
一定数のリクエスト後に再起動し、メモリ消費を確実に抑えます。
最小化されます。また、perlfuncで「my」を使って変数のスコープを設定すると良いでしょう。
可能。
パッケージ Embed::Persistent;
#persistent.pl
厳格な使用;
%Cache; です。
Symbol qw(delete_package); を使用します。
サブ有効なパッケージ名 {
my($文字列) = @_;
$string =~ s/([^A-Za-z0-9\/])/sprintf("_%2x",unpack("C",$1))/eg;
# 数字で始まる単語のみ2回目のパス
$string =~ s|/(\d)|sprintf("/_%2x",unpack("C",$1))|例;
# 実際のパッケージ名に似せる
$文字列 =~ s|/|::|g;
「埋め込み」$stringを返します。
}
サブ評価ファイル {
my($filename, $delete) = @_;
私の$package = valid_package_name($filename);
私の$mtime = -M $filename;
if(defined $Cache{$package}{mtime}
&&
$Cache{$package}{mtime} <= $mtime)
{
# このサブルーチンはすでにコンパイル済みです。
# ディスク上で更新されていないので、何もする必要はありません
STDERR に「$package->handler はすでにコンパイルされています\n」と出力します。
}
他{
ローカル*FH;
open FH, $filename または die "open '$filename' $!";
ローカル($/) = undef;
私の$sub = ;
クローズFH;
#コードを独自のパッケージ内のサブルーチンにラップします
my $eval = qq{パッケージ $package; サブハンドラー { $sub; }};
{
# このブロック内の変数を隠す
my($filename,$mtime,$package,$sub);
評価 $eval;
}
$ @の場合は$ @で死ぬ;
#毎回クリーンアップしない限りキャッシュする
$Cache{$package}{mtime} = $mtime ( $delete を除く)
}
{$package->handler;} を評価します。
$ @の場合は$ @で死ぬ;
$delete の場合は、delete_package($package) を実行します。
#よかったら見てください
#print Devel::Symdump->rnew($package)->as_string, $/;
}
1;
__終わり__
/* 永続的.c */
#含む
#含む
/* 1 = 各リクエスト後にファイル名のシンボルテーブルを消去する、
0 = しない
*/
#ifndef DO_CLEAN
#定義 DO_CLEAN 0
#endif
#BUFFER_SIZE 1024 を定義する
静的 PerlInterpreter *my_perl = NULL;
int型
main(int argc, char **argv, char **env)
{
char *embedding[] = { "", "persistent.pl" };
char *args[] = { "", DO_CLEAN, NULL };
char ファイル名[BUFFER_SIZE];
int 終了ステータス = 0;
PERL_SYS_INIT3(&argc,&argv,&env);
if((my_perl = perl_alloc()) == NULL) {
fprintf(stderr, "メモリがありません!");
終了する(1);
}
perl_construct(my_perl);
PL_origalen = 1; /* $0の代入で更新しないようにする
proctitleまたはembedding[0] */
exitstatus = perl_parse(my_perl, NULL, 2, 埋め込み, NULL);
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
if(!終了ステータス) {
終了ステータス = perl_run(my_perl);
while(printf("ファイル名を入力してください: ") &&
fgets(ファイル名, BUFFER_SIZE, stdin)) {
ファイル名[strlen(ファイル名)-1] = '\0'; /* \n を削除 */
/* サブルーチンを呼び出す、
ファイル名を引数として渡す */
args[0] = ファイル名;
call_argv("Embed::Persistent::eval_file",
G_DISCARD | G_EVAL, 引数);
/* $@ をチェック */
if(SvTRUE(ERRSV))
fprintf(stderr, "評価エラー: %s\n", SvPV_nolen(ERRSV));
}
}
PL_perl_destruct_level = 0;
perl_destruct(my_perl);
perl_free(my_perl);
PERL_SYS_TERM();
終了(終了ステータス);
}
次にコンパイルします:
% cc -o persistent persistent.c \
`perl -MExtUtils::Embed -e ccopts -e ldopts`
以下にスクリプト ファイルの例を示します。
#テスト.pl
私の$文字列 = "hello";
foo($文字列);
サブ foo {
print "foo says: @_\n";
}
次のコマンドを実行します:
% 持続的
ファイル名を入力してください: test.pl
fooは言います: こんにちは
ファイル名を入力してください: test.pl
すでにコンパイルされたEmbed::test_2epl->handler
fooは言います: こんにちは
ファイル名を入力してください: ^C
実行 of 終わり ブロック
伝統的にENDブロックはperl_runの最後に実行されていました。これにより
perl_runを呼び出さないアプリケーションでは問題が発生する。perl 5.7.2以降では、
新しい動作を得るには、「PL_exit_flags |= PERL_EXIT_DESTRUCT_END」を使用します。これにより、
perl_parseが失敗した場合、ENDブロックの実行は終了を返します。
の値です。
$0 割り当て
Perlスクリプトが$0に値を割り当てると、Perlランタイムはこの値を
argvが指すメモリを更新することで、「ps」によって報告されるプログラム名として表示されます。
に渡された perl_parse() また、次のようなAPI関数を呼び出すこともできます setproctitle() 利用可能な場合。
この動作はperlを埋め込む場合には適切ではない可能性があり、次のように無効にすることができます。
変数「PL_origalen」に値1を代入してから perl_parse() が呼び出されます。
当学校区の 永続的.c 上記の例では、$0が代入されたときにセグメントフォールトが発生する可能性があります。
「PL_origalen = 1;」の割り当てが削除された場合、Perlは
「埋め込み[]」文字列の読み取り専用メモリ。
保守 の試合に 通訳 インスタンス
まれに、アプリケーションによっては、セッション中に複数のインタープリターを作成する必要がある場合があります。
このようなアプリケーションは、散発的に、
通訳。
プログラムは、これが確実に行われるように注意する必要がある。 次の通訳者は
構築されます。デフォルトでは、Perlが特別なオプションなしでビルドされた場合、グローバル
変数「PL_perl_destruct_level」は、通常は追加のクリーニングは必要ないので0に設定されます。
プログラムがその存続期間中に 1 つのインタープリターのみを作成する場合。
「PL_perl_destruct_level」を 1 に設定すると、すべてがきれいになります。
while(1){
...
/* ここで PL_perl_destruct_level = 1 でグローバル変数をリセットします */
PL_perl_destruct_level = 1;
perl_construct(my_perl);
...
/* perl_destruct 中に _すべて_ をクリーンアップしてリセットします */
PL_perl_destruct_level = 1;
perl_destruct(my_perl);
perl_free(my_perl);
...
/* もう一度やりましょう! */
}
日時 perl_destruct() が呼び出されると、インタープリタの構文解析ツリーとシンボルテーブルが
クリーンアップされ、グローバル変数はリセットされます。2番目の代入は
perl_construct によって 0 にリセットされるため、「PL_perl_destruct_level」が必要です。
ここで、複数のインタプリタインスタンスが同時に実行されていると仮定します。これは
実行可能ですが、Configureオプション「-Dusemultiplicity」またはオプションを使用した場合のみです。
Perlをビルドする際に「-Dusethreads -Duseithreads」を指定します。デフォルトでは、これらのいずれかを有効にすると
設定オプションはインタープリタごとのグローバル変数「PL_perl_destruct_level」を1に設定します。
徹底的なクリーニングが自動的に行われ、インタープリタ変数が初期化される
正しく実行します。2つ以上のインタープリターを同時に実行するつもりがなくても、
上記の例のように、これらを順番に実行するには、perlを次のようにビルドすることをお勧めします。
「-Dusemultiplicity」オプションを指定しないと、一部のインタープリタ変数が初期化されない可能性があります。
連続実行間で正しく実行しないと、アプリケーションがクラッシュする可能性があります。
perlxs の「スレッド対応システム インターフェース」も参照してください。
以下の場合には、「-Dusethreads -Duseithreads」ではなく「-Dusemultiplicity」を使用する方が適切です。
複数のインタープリタを異なるスレッドで同時に実行することを意図している。
システムのスレッド ライブラリをインタープリターにリンクするためのサポートを有効にします。
試してみましょう:
#含む
#含む
/* 2つのインタープリターを埋め込みます */
#define SAY_HELLO "-e", "print qq(こんにちは、私は $^X\n です)"
int main(int argc, char **argv, char **env)
{
Perlインタープリタ *one_perl、*two_perl;
char *one_args[] = { "one_perl", SAY_HELLO };
char *two_args[] = { "two_perl", SAY_HELLO };
PERL_SYS_INIT3(&argc,&argv,&env);
perl_alloc() は、次のコードで呼び出されます。
2 つの perl を perl_alloc() で置き換えます。
PERL_SET_CONTEXT(one_perl);
perl_construct(one_perl);
PERL_SET_CONTEXT(two_perl);
perl_construct(2 つの perl);
PERL_SET_CONTEXT(one_perl);
perl_parse(one_perl, NULL, 3, one_args, (char **)NULL);
PERL_SET_CONTEXT(two_perl);
perl_parse(two_perl, NULL, 3, two_args, (char **)NULL);
PERL_SET_CONTEXT(one_perl);
perl_run(one_perl);
PERL_SET_CONTEXT(two_perl);
perl_run(2 つの perl);
PERL_SET_CONTEXT(one_perl);
perl_destruct(one_perl);
PERL_SET_CONTEXT(two_perl);
perl_destruct(2 つの perl);
PERL_SET_CONTEXT(one_perl);
perl_free(one_perl);
PERL_SET_CONTEXT(two_perl);
perl_free(2 つの perl);
PERL_SYS_TERM();
}
呼び出しに注意してください PERL_SET_CONTEXT()これらはグローバル状態を初期化するために必要である
特定のプロセスまたはスレッドでどのインタープリタが「現在」のものかを追跡します
実行している可能性があります。複数のインタープリタがある場合は必ず使用してください。
そして、両方のインタープリタでインターリーブ方式で Perl API 呼び出しを行っています。
PERL_SET_CONTEXT(interp)は、"interp"が以下のスレッドで使用されるたびに呼び出されるべきである。
作成しなかった(いずれかを使用して) perl_alloc()、あるいはもっと難解な perl_clone()).
通常どおりコンパイルします。
% cc -o 多重度 多重度.c \
`perl -MExtUtils::Embed -e ccopts -e ldopts`
実行してください。実行してください。
多重度(%)
こんにちは、one_perlです
こんにちは、two_perlです
使い方 パール モジュール、 which 自分自身 つかいます C ライブラリ、 from C プログラム
上記の例を試してみて、スクリプトを埋め込もうとしたなら、 使用()パール
モジュール(例: ソケット) 自体が C または C++ ライブラリを使用しているため、次のようなことが起こる可能性があります。
モジュール Socket をロードできません。この Perl では動的ロードは利用できません。
(新しいperl実行ファイルを作成する必要があるかもしれません。
動的ロードまたは Socket モジュールが静的にリンクされています。
何が気に入らないのだ。
インタープリタはこれらの拡張機能と単独で通信する方法を知りません。
少し接着剤を塗れば大丈夫。今まであなたは電話していた perl_parse()NULLを渡して
2番目の引数:
perl_parse(my_perl, NULL, argc, my_argv, NULL);
ここでグルーコードを挿入してPerlと
リンクされたC/C++ルーチン。いくつか見てみましょう perlmain.c Perlがどのように動作するかを見る
この:
静的 void xs_init (pTHX);
EXTERN_C void boot_DynaLoader(pTHX_ CV* cv);
EXTERN_C void boot_Socket(pTHX_ CV* cv);
EXTERN_C void
xs_init(pTHX)
{
char *ファイル = __FILE__;
/* DynaLoaderは特別なケースです */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, ファイル);
newXS("Socket::bootstrap", boot_Socket, ファイル);
}
簡単に言うと、Perl実行ファイルにリンクされた各拡張子(実行時に決定されます)に対して、
コンピュータの初期設定時や新しい拡張機能を追加するときなどにPerlサブルーチン
拡張機能のルーチンを組み込むために作成されます。通常、そのサブルーチンの名前は
モジュール::bootstrap() そして、あなたが言うときに呼び出されます つかいます モジュール. 次に、これが
XSUB、 ブートモジュールは、拡張機能の XSUB ごとに対応する Perl を作成します。
この部分については心配しないでください。 xsubpp 拡張機能の作者と。
拡張機能が動的にロードされると、DynaLoaderは モジュール::bootstrap() あなたのために
実際、DynaLoaderが動作していれば、リンクする必要はほとんどありません。
その他の拡張機能は静的に。
このコードができたら、それを次の2番目の引数に挿入します。 perl_parse():
perl_parse(my_perl、xs_init、argc、my_argv、NULL);
次にコンパイルします:
% cc -o interp interp.c `perl -MExtUtils::Embed -e ccopts -e ldopts`
% インタープリテーション
ソケットを使用します。
SomeDynamicallyLoadedModule を使用します。
print "これで拡張機能が使用できるようになりました!\n"'
ExtUtils :: Embed 書き込みを自動化することもできます xs_init グルーコード。
% perl -MExtUtils::Embed -e xsinit -- -o perlxsi.c
% cc -c perlxsi.c `perl -MExtUtils::Embed -e ccopts`
% cc -c interp.c `perl -MExtUtils::Embed -e ccopts`
% cc -o interp perlxsi.o interp.o `perl -MExtUtils::Embed -e ldopts`
詳細については、perlxs、perlguts、perlapi を参照してください。
使い方 埋め込まれた パール POSIX ローカル
(これらの情報についてはperllocaleを参照してください。)Perlインタープリタが通常起動すると、
システムのデフォルトロケールを使用するようにシステムに指示します。これはよくあることですが、
必ずしも「C」または「POSIX」ロケールである必要はありません。Perlコード内に「use locale」がない場合、これは
ほとんど効果はありません (ただし、perllocale の「「use locale」の範囲内ではない」を参照してください)。
また、埋め込みPerlで使用したいロケールが
システムのデフォルトと同じです。ただし、設定済みで使用したい場合はこの方法は使えません。
システムのデフォルトロケールではないロケール。Perl v5.20以降では、
組み込みPerlインタープリタはロケールが既に適切に設定されていることを確認し、
通常の初期化はスキップされます。環境変数
「PERL_SKIP_LOCALE_INIT」が設定されている場合(0または「」に設定されている場合も含む)。この機能を持つPerlは
Cプリプロセッサシンボル「HAS_SKIP_LOCALE_INIT」を定義します。これにより、
複数のPerlバージョンを操作して、問題に直面したときに何らかの回避策を実行する
以前の Perl。
隠蔽 パール_
PerlパブリックAPIの短縮形を完全に非表示にする場合は、-DPERL_NO_SHORT_NAMESを追加します。
コンパイルフラグに。つまり、例えば
warn("壁には%d本のビール瓶が置いてある", bottlecount);
明示的な完全形式を記述する必要があります
Perl_warn(aTHX_ "壁には%d本のビール瓶が置いてあります", bottlecount);
(perlgutsの「背景とPERL_IMPLICIT_CONTEXT」の説明を参照してください。
「aTHX_」。)短縮形を非表示にすることは、あらゆる種類の厄介な(C
プリプロセッサなど)は他のソフトウェアパッケージと競合します(Perlは約2400個の
これらの短い名前のAPIは数百個になるか、あるいは数百個になるかなので、
対立。)
道徳の
時々 書きます 速いです コード C言語では、いつでも 書きます コード 速いです Perl で。
それぞれを相互に利用することができるので、お好みに合わせて組み合わせてください。
onworks.net サービスを使用してオンラインで perlembed を使用する