<p>文章来自:http://www.aintnot.com/2016/02/04/phps-source-code-for-php-developers-ch</p> <p>原文:http://blog.ircmaxell.com/2012/03/phps-source-code-for-php-developers.html</p>
開発者として、私は日々の仕事の中で PHP ソースコードを見ることが増えています。舞台裏で何が起こっているのかを理解して、奇妙な境界問題や、何かが起こるべきときに何かが起こらない理由を解明するのに役立ちます。ドキュメントが不足している、不完全、または間違っている場合にも役立ちます。したがって、PHP 開発者に実際に PHP の C 言語ソース コードを読むのに十分な知識を提供するために、一連の記事を通じて私が学んだことを共有することにしました。 C の基本を知っている必要はありません (いくつかの基本をまとめます) が、知っていると役に立ちます。
これはこのシリーズの最初の記事です。この記事では、PHP プログラミングの基本、つまり、PHP プログラミングの場所、基本的なコード構造、および最も基本的な C 言語の概念について説明します。この一連の記事の目標は、ソース コードを読んで理解する能力を獲得することであることに注意してください。これは、特定のポイントを通過するために、特定の概念が過度に複雑な方法で説明されるのではなく、単純化されることを意味します。読む場合には目立った違いはありませんが、ソース コードに貢献したい場合は、さらに多くの知識を追加する必要があります。単純化するときは、それを指摘するようにしています。
さらに、この一連の記事はバージョン 5.4 のソース コードに基づいています。異なるバージョンでも、ほとんどの概念は同じですが、ここでは、この記事のバージョン定義が必要です (新しいバージョンを許可するため)。バージョンは後でリリースされます)下の記事の方がわかりやすいです)。
それで、始めてもいいですか?
PHP ソース コードをダウンロードする最も簡単な方法は、PHP の SVN リポジトリを使用することです。この記事では、5.4 ブランチをチェックアウトしました。これは、PHP の最先端にいる場合、または実際に PHP を開発している場合 (バグの修正、機能の実装など) に最適です。 PHP コミュニティが (この記事の執筆時点で) ソース コードを GIT リポジトリに移行していることは注目に値します。移行が完了して標準レベルに達したら、この投稿を更新します。 (翻訳者注: 翻訳者が翻訳した時点では、PHP は GIT ウェアハウスに移行されていました)。
実際、ソースコードをダウンロードすることは、私たちの目的にとってはあまり役に立ちません。これを編集するのではなく、単に使用して、その実行方法を追跡したいだけです。これをダウンロードして優れた IDE にインポートし、クリックすると関数の定義と宣言にジャンプできますが、これは思ったよりも少し難しいことがわかりました。もっと良い解決策があります。
PHP コミュニティが私たちにとって非常に優れたツールを維持していることがわかりました。それが lxr.php.net です。これは主に、構文の強調表示とすべての関数へのリンクを備えた、自動的に生成された検索可能なソース コード リストです。これは、私が C ソース コードを参照するためにほぼ独占的に使用するツールであり、素晴らしいものです (パッチを作成しているときでも、開発中のコードベースではなく lxr を使用します)。より効率的な検索を行う方法についてはまだ説明しませんが、PHP のコア機能について説明するときに説明します。
ここからはPHP5.4の話になります。この目的のために、この lxr リンクを他の記事の基礎として使用します。 「5.4 のルート ディレクトリ」とはこのページのことを指します。
ソース コード ディレクトリを表示できるようになったので、その内容について説明しましょう。
さて、5.4 のルート ディレクトリにリストされているファイルとディレクトリを見ると、さらに調査すべきことがたくさんあります。 ext と Zend の 2 つのディレクトリだけに注目してください。他のファイルとディレクトリは PHP 拡張機能と開発にとって重要ですが、ここでの目的のためには完全に無視できます。では、なぜこれら 2 つのディレクトリがそれほど重要なのでしょうか?
PHP プログラムは、ご想像のとおり、2 つの主要な部分に分かれています。最初の部分は Zend エンジンで、PHP コードの実行時に実行環境を制御します。これは、変数、式、構文解析、コード実行、エラー処理など、PHP が提供するすべての「言語層」機能を処理します。このエンジンがなければ、PHP は存在しません。エンジンのソース コードは Zend ディレクトリに配置されます。
PHP の 2 番目のコア部分は、PHP に含まれる拡張機能です。これらの拡張機能には、PHP で呼び出すことができるすべてのコア関数 (strpos、substr、array_diff、mysql_connect など) が含まれています。コアクラス (MySQLi、SplFixedArray、PDO など) も含まれます。
コア コード内で確認したい機能がどこにあるかを判断する最も簡単な方法は、PHP ドキュメントのホームページを参照することです。 PHP のドキュメントも、(私たちの目的では) 言語リファレンスと関数リファレンスという 2 つの主要なセクションに分かれています。要約すると、言語リファレンスで定義を確認したい場合は、Zend フォルダーで見つかる可能性が高くなります。関数リファレンスにある場合は、ext フォルダーにあります。
このパートは C の入門を目的としたものではなく、「読者向けのガイド」を目的としています。次の概念があります:
C では、変数は静的であり、厳密に型指定されます。これは、変数を使用する前に、その変数を型で定義する必要があることを意味します。一度定義すると、その型を変更することはできません (後で別の型に変換できますが、そのためには別の変数を使用する必要があります)。なぜなら、C言語では実際には変数が存在しないからです。これらは、私たちが使用するメモリアドレスの便利なラベルにすぎません。このため、C には PHP の参照がありません。代わりに、ポインタがあります。ここでは、ポインターを他の変数を指す変数と考えてください。 PHP の変数の変数と考えてください。
それでは、上記の説明を踏まえて、変数の構文について話しましょう。 C 言語では、変数を識別するために接頭辞を使用しません。したがって、(私たちの目的において) それらがどのように異なるかを知る唯一の方法は、それらの定義を確認することです。関数の先頭 (または関数の宣言内) の型とスペースの後に文字がある場合、それは変数です。注意すべき重要な点は、変数名の前に 1 つ以上の記号を付けることができるということです。アスタリスク (*) は、変数が特定の型 (参照) へのポインターであることを示します。 2 つのアスタリスクは、変数がポインターへのポインターであることを示します。 3 つのアスタリスクは、変数が別のポインターへのポインターであることを示します。
PHP は内部で多くの 2 レベル ポインターを使用するため、この間接アドレス指定は非常に重要です。これは、エンジンがデータのチャンク (PHP 変数) や、PHP 参照、コピーオンライト、オブジェクト参照などの興味深いタイプをすべて渡すことができる必要があるためです。したがって、**ptr は 2 レベルの参照 (変数への参照ではなく、データ参照への参照) を使用していることを意味することに注意してください。これも少しややこしいですが、引用がまったく初めての場合は、これを読むことをお勧めします (ただし、C を読む必要があるわけではありません)。それが役立ちます。
さて、ポインタについて理解すべきもう 1 つのことは、ポインタが C の配列 (PHP の配列ではなく、C の配列) をどのように扱うかということです。ポインタはメモリ アドレスであるため、メモリのブロックを割り当てることで配列を定義し、ポインタをインクリメントすることで配列を反復処理できます。通常の状況では、文字 (8 ビット) を表す C データ型 char を使用して、文字を文字列に格納できます。ただし、これを配列のように使用して、文字列の末尾のバイトにアクセスすることもできます。したがって、文字列を変数に格納する代わりに、最初のバイトにポインタを格納するだけで済みます。次に、ポインタをインクリメントして (メモリ アドレスを増やして)、文字列全体を反復処理します。
<span class="hljs-keyword">char *foo = <span class="hljs-string">"test"; <span class="hljs-comment">// foo 是指向"t"在内存的片段保存"test"的指针 <span class="hljs-comment">// 要访问"e",我们可以通过下面的方式: <span class="hljs-keyword">char e = foo[<span class="hljs-number">1]; <span class="hljs-keyword">char e = *(foo + <span class="hljs-number">1); <span class="hljs-keyword">char e = *(++foo); </span></span></span></span></span></span></span></span></span>
C の変数とポインターについてさらに詳しく知りたい場合は、この素晴らしい無料書籍をチェックしてください。
C はコンパイル前に「前処理」と呼ばれるステップを使用します。このステップには、コンパイラに渡すオプションに基づいてコードの一部を最適化し、動的に使用することが含まれます。条件文とマクロという 2 つの主要なプリプロセッサ仕様について説明します。
条件ステートメントを使用すると、出力をコンパイルするとき、または定義に基づいていないときにコードを導入できます。これは以下の例によく似ています。これにより、異なるオペレーティング システムに基づいて異なるコードを使用できるようになります (そのため、Windows と Linux では、異なる API を使用している場合でも正常に動作します)。さらに、定義された命令に基づいてコードの一部を導入したり、導入しなかったりすることもできます。実際、これは構成ステップ中に PHP がコンパイルされる方法です。
<span class="hljs-preprocessor">#<span class="hljs-keyword">define FOO 1 <span class="hljs-preprocessor">#<span class="hljs-keyword">if FOO Foo <span class="hljs-keyword">is defined and not <span class="hljs-number">0 <span class="hljs-preprocessor">#<span class="hljs-keyword">else Foo <span class="hljs-keyword">is not defined or <span class="hljs-keyword">is <span class="hljs-number">0 <span class="hljs-preprocessor">#<span class="hljs-keyword">endif <span class="hljs-preprocessor">#ifdef FOO Foo <span class="hljs-keyword">is defined <span class="hljs-preprocessor">#<span class="hljs-keyword">else Foo <span class="hljs-keyword">is not defined <span class="hljs-preprocessor">#<span class="hljs-keyword">endif </span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>
別の説明は、私がそれをマクロと呼んでいるということです。これは、コードを簡素化するための最も単純なミニ関数です。これらは実際の関数ではありませんが、コンパイル前処理中に単純なテキスト置換を実行します。したがって、マクロは実際には関数を呼び出しません。関数定義のマクロを作成できます (実際、これは PHP が行うことですが、これについては後の記事で説明します)。私が言いたいのは、マクロを使用すると、コンパイルの前処理時により単純なコードが可能になるということです。
<span class="hljs-comment">#define FOO(a) ((a) + 1) <span class="hljs-keyword">int b = FOO(<span class="hljs-number">1); <span class="hljs-regexp">// Converted to <span class="hljs-keyword">int b = <span class="hljs-number">1 + <span class="hljs-number">1 </span></span></span></span></span></span></span>
最後の部分では、C ソース コードで使用される 2 種類のファイルを理解する必要があります。ファイルには主に .c と .h の 2 種類があります。 .c ファイルは、コンパイルの準備ができたソース コードを含むファイルです。一般に、.c ファイルには、他のファイルと共有できないプライベート関数の実装が含まれています。 .h (またはヘッダー ファイル) は、前処理マクロなど、他のファイルから参照できる .c ファイル内の関数を定義します。ヘッダー ファイルでパブリック API を定義する方法は、関数本体を使用せずに関数のシグネチャを再宣言することです (PHP のインターフェイスや抽象メソッドと同様)。このようにして、ヘッダー ファイル を介してソース コードをリンクできます。
次のパートstrlen など) にジャンプして、その定義とその動作を確認できます。このリズムを保ってください。