Upgrade to Pro — share decks privately, control downloads, hide ads and more …

転ばぬ先のXS入門 / YAPC::Fukuoka 2025

Avatar for polamjag polamjag
November 15, 2025

転ばぬ先のXS入門 / YAPC::Fukuoka 2025

Avatar for polamjag

polamjag

November 15, 2025
Tweet

More Decks by polamjag

Other Decks in Technology

Transcript

  1. 6

  2. 12

  3. CPANモジュールをインストールすると き - ビルドツール - Makefile.PL: ExtUtils::MakeMaker - perl Makefile.PL

    で Makefile が生成される - Build.PL: Module::Build, Module::Build::Tiny - perl Build.PL で Build というファイル名のシェルスク リプトが生成される - オーサリングツール - Minilla, Dist::Zilla, … 22
  4. CPANモジュールをインストールすると き - App::cpm のインストール処理を覗いてみると… - fetch, configure, install の三段階

    - そのうち configure で Makefile.PL や Build.PL を探して実行 - install で↑ で生成されたものを実行 - https://github.com/skaji/cpm/blob/74e217556acec88fe798 d4935efe7a9c50d19e28/lib/App/cpm/Worker/Installer.pm - static install (ビルドスクリプトの実行なしに、ファイルのコピーのみ のインストール) という概念もある - https://github.com/Perl-Toolchain-Gang/cpan-static 23
  5. 「XS」はプログラミング言語だった! - XS - xsubpp -> C - xsubpp -

    compiler to convert Perl XS code into C code - https://perldoc.perl.org/xsubpp - “This compiler is typically run by the makefiles created by ExtUtils::MakeMaker or by Module::Build or other Perl module build tools” - ExtUtils::ParseXSに実装がある - https://github.com/Perl/perl5/blob/blead/dist/ExtUtils-ParseXS/lib/ExtUtils /ParseXS.pm - 「大規模なリファクタリングが始まっている」!! - https://speakerdeck.com/charsbar/2025nian-qiu-noperl?slide=59 28
  6. Perl ランタイム 共有ライブラリ (*.dll, *.so, *.dylib, …) 静的ライブラリ ビルド時に静的リンク ビルド時に動的リンク

    or 実行時に動的ロード PerlのXSは静的リンクも可能 (!) だが、Webアプリケーションの開発という文脈においては 動的ロードを想定したXSライブラリの利用がほとんどであるはず…… 😮 34
  7. (Web開発でよく出会う) XSモジュールの類型 - 特定処理の最適化 - /デ?シリアライズ/ (e.g. JSON::XS) - テンプレートエンジン

    (e.g. Text::Xslate) - ネイティブライブラリのラッパー - e.g. DBD::mysql (→ libmysqlclient) - 言語ランタイムの機能拡張的な側面 - e.g. AnyEvent (RubyでいうEventMachine的な存在[要出典]) 35
  8. Perlランタイム Perlプログラム (*.pl, *.pm) 共有 ライブラリ (XS由来) 動的ロード 共有 ライブラリ

    (外部) 動的リンク 「ネイティブライブラリのラッパー」 の典型的なシーン PerlのXSは静的リンクも可能 (!) だが、Webアプリケーションの開発という文脈においては 動的ロードを想定したXSライブラリの利用がほとんどであるはず…… 😮 36
  9. Perlランタイム DBD::mysql (のPerl部分) DBD::mysql (のXS由来部分) 動的ロード libmysql- client 動的リンク DBD::mysqlの典型的な利用イメージ

    DBD::mysqlのXS由来部分から、どうlibmysqlclientをリンクするか話も当然ありまして…… https://metacpan.org/dist/DBD-mysql/view/lib/DBD/mysql/INSTALL.pod 💁 DBD::mysql 37
  10. 「ネイティブ拡張」? - perlxstut - Tutorial for writing XSUBs (Perl) https://perldoc.perl.org/perlxstut

    - “a Perl extension” - Gems with Extensions (RubyGems) https://guides.rubygems.org/gems-with-extensions/ - “Many gems use extensions to wrap libraries …” - Extending Python with C or C++ (Python) https://docs.python.org/3/extending/extending.html - “extension modules” - C++ addons (Node.js) https://nodejs.org/api/addons.html - “Addons are dynamically-linked shared objects written in C++” 44
  11. 「ネイティブ拡張」? - perlxstut - Tutorial for writing XSUBs (Perl) https://perldoc.perl.org/perlxstut

    - “a Perl extension” - Gems with Extensions (RubyGems) https://guides.rubygems.org/gems-with-extensions/ - “Many gems use extensions to wrap libraries …” - Extending Python with C or C++ (Python) https://docs.python.org/3/extending/extending.html - “extension modules” - C++ addons (Node.js) https://nodejs.org/api/addons.html - “Addons are dynamically-linked shared objects written in C++” 45
  12. こういうことやりませんでしたか $ cpanm -L local DBD::mysql \ --configure-args="--cflags='$(pkg-config --cflags mysqlclient)'

    \ --libs='$(pkg-config --libs mysqlclient)'" $ CFLAGS="-I$(brew --prefix openssl)/include" LDFLAGS="-L$(brew --prefix openssl)/lib" carton install 50
  13. Perlランタイム Perlプログラム (*.pl, *.pm) 共有 ライブラリ 動的ロード 共有 ライブラリ 動的リンク

    「ネイティブライブラリのラッパー」 的なシーン どれを? どれを? 🤔 52
  14. Perlランタイム Perlプログラム (*.pl, *.pm) 共有 ライブラリ 動的ロード 共有 ライブラリ 動的リンク

    「ネイティブライブラリのラッパー」 的なシーン CPAN モジュールの 単位 53
  15. Perlランタイム Perlプログラム (*.pl, *.pm) 共有 ライブラリ 動的ロード 共有 ライブラリ 「ネイティブライブラリのラッパー」

    的なシーン XSから生成される共有ライブラリと、 OSのどこかにあるライブラリとの間の関係 動的リンク 54
  16. こういうことやりませんでしたか $ cpanm -L local DBD::mysql \ --configure-args="--cflags='$(pkg-config --cflags mysqlclient)'

    \ --libs='$(pkg-config --libs mysqlclient)'" $ CFLAGS="-I$(brew --prefix openssl)/include" LDFLAGS="-L$(brew --prefix openssl)/lib" carton install XSから生成される共有ライブラリを ビルドするにあたり、 OSのどこにあるライブラリと 紐づけるかの指定 55
  17. Perlランタイム DBD::mysql (のPerl部分) DBD::mysql (のXS由来部分) mysql_configコマンドを 呼び出したり 環境変数やオプションで指 定できたり (写ってない)

    DBD::mysqlの Makefile.PL再び 57 https://github.com/perl5-dbi/DBD-mysql/ blob/6465c04c62d23ce42b08b90ea33636 30187e1739/Makefile.PL#L423-L469
  18. perldocの歩き方 - perlxs, perlapi など perl*** みたいな名前の ドキュメントがたくさん - C

    APIもしっかりドキュメントがある - 例: perlguts (Perl APIの導入) を読むには… - https://perldoc.perl.org/perlguts - https://perldoc.jp/docs/perl/perlguts.pod - $ perldoc perlguts 64
  19. Cpanel::JSON::XS use Cpanel::JSON::XS qw(encode_json decode_json); my $encoded = encode_json( {

    foo => 1, bar => [2, 3] } ); my $parsed = decode_json('{"foo":1,"bar":[2,3]}'); 69
  20. “キーワード MODULE は XS コードの始まりと、定義する関数のパッケージ を指定するのに使われます。 キーワード MODULE よりも前にあるテキスト はCプログラムとして扱われ、

    POD が除去されますが、それ以外は何の変更 も加えられずに出力されます” https://perldoc.jp/docs/perl/5.8.8/perlxs.pod#The32MODULE32Keyword 71
  21. 72

  22. XSUB - perldoc.jp/docs/perl/perlxs.pod - “XSUB は XS インターフェースの基本単位を形成し ます。xsubpp コンパイラによるコンパイル後、

    それ ぞれの XSUB は Perl 呼び出し規則と C 呼び出し規則 の間の糊を提供する C 関数定義となります” - XSUB1個 = Perl上での関数定義1個 74
  23. SV - see perlguts - SV: Scalar Value - とる値:

    “整数 (IV)、符号なし整数 (UV)、 倍精度 (NV)、文字列 (PV)、その他のスカラ (SV)” - ほか AV (Array Value), HV (Hash Value), RV (Reference Value), … 77
  24. スタックの管理 - PUTBACK 〜 SPAGAIN - PUTBACK: XSUB内でのローカル変数なスタックポイ ンタの内容を、Perlランタイムのそれ (PL_stack_sp)

    に書き込み - SPAGAIN: ↑の逆 (Perlランタイム → XSUB内のローカ ル変数スタックポインタ) 83
  25. "コンテクストポインタ" を 受け取るマクロ mortalフラグのセット スコープを抜ける際に参照カウンタを デクリメント SvPVX: PV (文字列) へのポインタ

    SvEND: PV (文字列) の終端位置への ポインタ XSの関数定義 (XSUB) じゃなかった方の encode_jsonも見る 86
  26. SvPOK_only: “SV に対し、その SV が文字列であり、 他の OK ビットをすべてディセーブルにするように指 示します。また、UTF-8 ステータスをオフにします”

    (perlapi) aTHx_: コンテキストポインタを 「渡す」マクロ SVの 文字数セット SVのUTF-8フラグを立てる encode_svがSV一つを エンコードする処理 87
  27. DBD::mysql - “MySQL driver for the Perl5 Database Interface (DBI)”

    - DBI: Database Interface - DBD: Database Driver - DBD::mysql の他には DBD::Pg, DBD::SQLite など - DBD::** implements DBI 的な関係 94
  28. 102

  29. 上に PREFIX = my_ 指定があるので これが rb_eval 関数の定義になる (see perlxs)

    PREINIT: typemap 機能に影響されずに 変数宣言をするセクション 106
  30. VALUE型 = Rubyオブジェクト newSViv = IV (integer) から SV を生

    成 newSVnv = NV (double型) から SV newSVpvn = PV (char *) とその長さか ら SV https://docs.ruby-lang.org/en/ master/extension_rdoc.html rb2pl (!!) 108
  31. rb_ary_entry でRubyの配列 から値を取り出し、その要素を 再帰的に rb2pl し、av_push で Perlの配列に追加 newRV_noinc() で

    AV (retval) からリファレンス を取得 _noinc はリファレンスカ ウントを増加させない版 API newAVで AV (Array Value) を 作成 newHVで HV (Hash Value) を 作成 109
  32. typemap - see perlxstypemap - Cレベルの型 ←→ Perlのデータ型の変換機構 - char

    * を簡単にPVにしたい、みたいなことができる - xsubppで処理されるので、それが嬉しくないという ときは実装を PPCODE: セクションに書く…というの がCpanel::JSON::XSで出てきていた 111
  33. 改めて List::Util::min active magic = 演算子オーバーロード amagic_call(SV *left, SV *right,

    int method, int dir) 118 ix: ALIASごとのインデックス これを使ってmax/minを一つの XSUBで実装している
  34. XS 別解 - FFI - ex. https://metacpan.org/pod/FFI::Platypus - 別バイナリ化 +

    プロセス間通信 - WASM - XSと比べるとオーバーヘッドがあったり、ラ ンタイムの機能拡張は難しかったり 120
  35. 121

  36. (おまけ) 超私的・大分観光案内 - JR九州の割引きっぷがある (九州ネットきっぷ 他) - 別府の市営温泉に入ろう (“別府 市営温泉”

    で検索) - 別府で冷麺を食べよう (“別府冷麺” で検索”) - 焼鳥、アジ、ヒラメを食べよう - やまなみハイウェイをドライブしよう - ホバークラフトに乗ってみて感想教えてくだ さい (乗ったことない…) 126
  37. 127