Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP Internals わいわい #3 mb_*関数を作ってみよう
Search
てきめん tekimen
PRO
December 22, 2024
Programming
0
51
PHP Internals わいわい #3 mb_*関数を作ってみよう
本来はPHPカンファレンス2024で発表する予定の資料でしたが、体調不良で参加できなかったため作成しました。
てきめん tekimen
PRO
December 22, 2024
Tweet
Share
More Decks by てきめん tekimen
See All by てきめん tekimen
Windows版php-srcデバッグ方法
youkidearitai
PRO
1
50
PHP Internals わいわい #1 の資料
youkidearitai
PRO
1
1.1k
mb_trim関数を作りました
youkidearitai
PRO
1
790
PHPの次期バージョンはこの時期どうなっているのか - Internalsの開発体制について - PHPカンファレンス小田原
youkidearitai
PRO
1
680
文字とはなにか - PHPの文字コード処理について - PHP Lovers Meetup #5
youkidearitai
PRO
1
240
はじめてのOSSコントリビュート
youkidearitai
PRO
11
3.7k
文字とはなにか - PHPの文字コード処理について -
youkidearitai
PRO
0
740
現在のmbstringの立ち位置 これからどうなっていくのか
youkidearitai
PRO
0
260
PHP 8.3のmbstringの進化を見てください - コントリビューターとしてのかかわり -
youkidearitai
PRO
0
1.3k
Other Decks in Programming
See All in Programming
動作確認やテストで漏れがちな観点3選
starfish719
6
1k
Domain-Driven Transformation
hschwentner
2
1.9k
Compose でデザインと実装の差異を減らすための取り組み
oidy
1
300
密集、ドキュメントのコロケーション with AWS Lambda
satoshi256kbyte
0
130
Spring gRPC について / About Spring gRPC
mackey0225
0
220
Grafana Loki によるサーバログのコスト削減
mot_techtalk
1
110
社内フレームワークとその依存性解決 / in-house framework and its dependency management
vvakame
1
550
Djangoアプリケーション 運用のリアル 〜問題発生から可視化、最適化への道〜 #pyconshizu
kashewnuts
1
210
お前もAI鬼にならないか?👹Bolt & Cursor & Supabase & Vercelで人間をやめるぞ、ジョジョー!👺
taishiyade
5
3.6k
Kanzawa.rbのLT大会を支える技術の裏側を変更する Ruby on Rails + Litestream 編
muryoimpl
0
210
Flutter × Firebase Genkit で加速する生成 AI アプリ開発
coborinai
0
140
Honoをフロントエンドで使う 3つのやり方
yusukebe
1
380
Featured
See All Featured
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
114
50k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
11
940
Scaling GitHub
holman
459
140k
Documentation Writing (for coders)
carmenintech
67
4.6k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
29
2.2k
4 Signs Your Business is Dying
shpigford
182
22k
Designing for Performance
lara
604
68k
GraphQLとの向き合い方2022年版
quramy
44
13k
Transcript
PHP Internals わいわい mb_*関数を作ってみよう!
自己紹介 てきめん • https://tekitoh-memdhoi.info • X: @youkidearitai • https://github.com/youkidearitai •
PHP 8.4で複数の関数を作りました – mb_trim, mb_ltrim, mb_rtrim – mb_ucfirst, mb_lcfirst – grapheme_str_split オレ
アジェンダ • まずはPHPをコンパイル! • mbstring拡張について内部構造の解説 • mb_*関数の検討 • 作成 •
テスト
趣旨 • PHP Internals Bookを元に、PHPのソースコード、php-srcを 取得、コンパイルしたりソースコードを読みます – https://www.phpinternalsbook.com/ – あわよくばバグを見つけたら報告したり
– あわよくばテストコードを修正したり – 更に行けば関数・機能を追加するとか • PHP Internalに向かって新機能を追加する提案をしたりで きないかと思っています
コンパイルの前段階 • Linuxを用意します • 今回はDockerを使います – WSLやmultipass、limaなどを使ってもらっても構いま せん
PHPのコンパイルの準備 > docker pull ubuntu:22.04 > docker run -it ubuntu:22.04
bash # apt update && apt install -y pkg-config build- essential autoconf bison re2c libxml2-dev libsqlite3-dev gdb git libonig-dev # cd ~ # /root # git clone https://github.com/php/php-src
PHPのコンパイルの準備 # cd php-src # ./buildconf -f # ./configure --enable-debug
--enable-mbstring # make # make test # make install # --prefix を指定していないので/usr/local/に入る # php -v #これで実行できる!
この状態を保存します • Command + p + qで抜けるか、もしくは別のコンソー ルを開いてください • >
docker ps で開いているContainer IDを調べます • > docker commit [container id] ubuntu:php85 – このようにすればubuntu:php85で今までの作業した内容 を保存して、コンパイルできた状態で入れます
このようにコンテナを作れました > docker run -it ubuntu:php85 root@ea6b72b5f128:/# php -v PHP
8.4.0-dev (cli) (built: May 31 2024 00:57:46) (NTS DEBUG) Copyright (c) The PHP Group Zend Engine v4.4.0-dev, Copyright (c) Zend Technologies
tips • 今回はDockerを使いましたが、LinuxやmacOS内 部で複数のPHPを持ちたいときは --prefix オプ ションが便利です。 – --prefix=$HOME/php84 とかしてあげると、ホームディ
レクトリ配下にバージョンごとにコンパイル・インストー ルができるわけです。
デバッグ手法 • Linuxではgdbとかlldbなどが使えますが、今回はgdb を使います • コンテナ内部でvimとctagsなどを利用してソースコー ドを読みます – 手元でコンパイルできるとVisual Studio
Codeがつかえた りするようですね • https://php.github.io/php-src/introduction/ides/visual-studi o-code.html – このあたり知ってる人は共有してくれると嬉しい
開発環境を揃える # apt install exuberant-ctags vim # cd ~/php-src #
ctags -R . # カレントディレクトリが/root/php-src
コンパイルオプションあれこれ 変数 CC をつけるとコンパイラを指定できます 変数 CFLAGS でコンパイルオプションを指定できま す 例: CC=clang
CFLAGS=”-g” ./configure –enable- debug # clangでコンパイルし、-gオプションを加え られます
テストについて https://www.phpinternalsbook.com/tests/runni ng_the_test_suite.html # sapi/cli/php run-tests.php # すべてのテストを行 う #
sapi/cli/php run-tests.php -P ext/mbstring # mbstring拡張のみテストする
いざmbstring関数の実装へ • これで準備はおわりました • mbstring関数の実装をしていきましょう – mb_my_function関数を作ります • 仕様として、「最初の1文字を取り除いてEUC-JPに変換する」 としましょう
どうしてmbstringか • CJK(China, Japan, Korea)ユーザーはこの拡張に とてもお世話になります • 母国語を日本語とする我々はPHPのアドバンテー ジがここにあります •
mbstringへのコントリビュートがPHPへのコントリ ビュートの近道だと考えています
関数の作成 • 今回のゴールは関数の作成です • まずは関数の作り方を学びます • mbstringで関数を作るので、ext/mbstringに作業 します。ただし、カレントディレクトリはphp-srcのトッ プディレクトリです –
ctagsで作ったtagsファイルでジャンプしたいため
stubファイルを編集しスタブを追加
スタブを追加
関数を書きます ext/mbstring/mbstring.cを編集します。 まずは引数を取り、何もしない関数を作りま す。 引数はZEND_PARSE_PARAMETERS_START、 ZEND_PARSE_PARAMETERS_ENDで囲みま す。 $encodingが不正な場合は例外をスローしてい ます。
mbstringのルール • 内部ではUTF-32で動いています(UCS方式) – たとえば、Shift_JISからEUC-JPでは • Shift_JIS → UTF-32 →
EUC-JP となります – データ型はuint32_tで取ります • 32bit(4byte)ですね
内部で使える関数 • mb_get_strlen – mb_strlenの内部実装関数です。 • mb_get_substr – mb_substrの内部実装関数です。 •
mb_fast_convert – mb_convert_encodingの内部実装関数です。 • mb_fast_convert関数で内部でUTF-32に変換して目的の文字エンコー ディングに変換しています、これがUCS方式
mb_fast_convertの実装 338行目でUTF-32 に変換し、341行目 でUTF-32から目的 のエンコーディン グに変換している
mb_get_strlenの実装 mb_fast_strlen_ utf8は難しいので 読まなくていい to_wcharメソッド がコードポイント長 を返すので、それを 足して返す実装に なってる
中身を作ります まず、 mb_get_substrで 1文字だけ取り除き ます。長さは短い 方を取ってくれま す。 次に、 mbfl_name2enco dingでEUC-JPのイ
ンスタンスを取 得、 mb_fast_convert 関数で変換、 retを開放で終わり
動作確認 ハローワールドという文字列から、最初の1文字を抜き取ってEUC-JPに変換すること に成功しました! 出力の確認でmb_convert_encodingを挟んでいますが、mbstringのお作法がちょっ とでもわかると嬉しいです
テストの作成 • テストを書きま しょう • ext/mbstring/ tests/ mb_my_functio n.phpt に作成し
ます
テストの実行 sapi/cli/php run-tests.php -P ext/mbstring/tests/mb_my_fun ction.phpt これで実行してPASS を確認します。
さらなる冒険へ • これはちょっと高レベルな世界かと思われます • もっと実装の方に行くと、さらなる知見が得られると 思います • でも、既存のコードで新しい関数を開発することは 可能ですから、色々いじってみてください
おわり • 今回はmb_my_function関数を作り、変換と substrを体験しました • これだけでもちゃんと新しい関数が作れますが、C 言語の知識ともっとmbstringのソースコードの探 求をすると効率の良いコードが書けます • Enjoy!