SlideShare a Scribd company logo
1 of 35
Download to read offline
PHPからC#のライブラリを
呼べるようにしたdotnet_ffiを
趣味でつくってみた
よーがす @pg_ito
(アバター: 佐波野いりこ @SabanoIriko)
PHP Conference Japan 2022 09/25
自己紹介
● エンジニア
最近は主にPHP、C#、たまにC++、JavaScript
サーバの負荷対策が好き
● 趣味
配信、電子工作、スプラトゥーン3
名前: よーがす
Twitter: @pg_ito
Blog: https://b64.pw/blog/
もくじ
● dotnet_ffiってなに?
● 作った動機
● 想定される利用ケース
● dotnet_ffiの構成
● dotnet_ffiの簡単な使い方
● CoreCLRって?
● Extensionを作るための情報源
● 今後の展望
dotnet_ffiってなに?
dotnet_ffiってなに?
PHPからC#のライブラリを直接呼べるようにしたPHP Extension
CoreCLRをつかってC#のDLLを動的にロード、実行している
PHPプロセスが作り直されるまでC#のVMを使いまわすので
C#のJITの恩恵を得られて高速に動作
リポジトリ: https://github.com/pg-ito/dotnet_ffi
(MITライセンス)
パフォーマンス比較
fibonacci数を計算させた場合PHPのみに比べて約16倍ほど高速(PHP8.1.6の場合)
作った動機
作った動機
・Unityと同じ処理をPHPサーバ側でも行いたい
・Extensionを書かずに手軽にPHPの処理を高速化したい
・C#にしかない機能を使いたい
想定される利用ケース
UnityClientと処理の共通化
・ゲームのチート対策
クライアントから送られてきたデータが不正なものでないか
正規のクライアント側のC#の処理と比較できる
・バリデータの共通化
APIのエラーチェックなどを一元化できる
処理の高速化
・CPU使用率の高い処理をC#側で高速に行える
例えばfibonacci数を求めるような処理で効果を発揮
(リポジトリ内のベンチマークにこのケースを想定したコードを同梱)
C#にしかないライブラリの利用
・Linqでのデータの抽出
多次元配列を任意の形に整形
(おそらくPHPのみで書かれている限りPHP移植版Linqにくらべて高速な…ハズ)
dotnet_ffiの構成
PHP Process
設計の特徴
・PHP ExtensionがC/C++で書けることを利用してCoreCLR経由でC#とバインド
PHP ➡ dotnet_ffi(C,C++) ➡ CoreCLR(C++) ➡ C# Library
PHP 標準
Extension
CoreCLR (C++)
C# Library
PHP
標準関数等
PHP
言語
構造
dotnet_ffi (C, C++)
※CoreCLRについては後述
PHP8対応での影響
・ARG_INFOの対応
PHP8でビルドするとついにwarningが出るようになった。
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &arg1, &arg2) == FAILURE) {
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ret_s64_arg_s64_s64,
0, 2, IS_LONG, 0)
ZEND_ARG_INFO(0, long_arg1)
ZEND_ARG_INFO(0, long_arg2)
ZEND_END_ARG_INFO()
PHP_ME(DotnetFFI, ret_s64_arg_s64_s64, arginfo_ret_s64_arg_s64_s64,
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
型情報を追加
dotnet_ffiの簡単な使い方
ビルド
・ソースのクローン
git clone https://github.com/pg-ito/dotnet_ffi.git .
・docker composeでビルドと実行
cd build_env
docker compose -up -d --build
docker compose exec php_fpm /bin/bash -c "cd /var/www && ./br.sh && ./run.sh"
・もし直接ビルドする場合
yum install -y devtoolset-7-gcc devtoolset-7-gcc-c++
yum install -y --enablerepo=epel,remi,remi-php81 php php-devel
yum install -y dotnet-sdk-6.0
./br.sh
dotnet_ffiの簡単な使い方
・引数がint、戻り値もintの場合の呼び出し方
$retInt64 = DotnetFFI::ret_s64_arg_s64(30);
※デフォルト設定だとdotnet_dllディレクトリにある
fibonacci数のサンプルコードを呼び出すようになっている(iniで変更可)
・実行
docker compose exec php_fpm /bin/bash -c "cd /var/www && ./run.sh mycode.php"
・その他サンプルコード
./ext_test.php … 各種メソッドの動作サンプル
./benchmarker/runbench.php … フィボナッチのベンチマーク
CoreCLRって?
CoreCLRって?
・.NETの実行環境
ほかのC/C++のプログラムに.NETのVM(※CLI)を
組み込むことができるライブラリ(というかこれ自体で.NETを動かしている)
dotnet_ffiはこれを使ってPHP ExtensionからC#を実行している
※CLI…Common Language Infrastructure
※CoreCLRリポジトリ
https://github.com/dotnet/coreclr/tree/v3.1.29
・CoreFX、Mono Runtime等と類似の役割
※参考: Embedding Mono
https://www.mono-project.com/docs/advanced/embedding/
CoreCLRの使い方(初期化)
・libcoreclr.soをdlopenする
coreClr = dlopen(coreClrPath.c_str(), RTLD_NOW | RTLD_LOCAL);
・dlsymでそれぞれのシンボルのアドレスを取得
initializeCoreClr = (coreclr_initialize_ptr)dlsym(coreClr, "coreclr_initialize");
createManagedDelegate = (coreclr_create_delegate_ptr)dlsym(coreClr,
"coreclr_create_delegate");
shutdownCoreClr = (coreclr_shutdown_ptr)dlsym(coreClr, "coreclr_shutdown");
CoreCLRの使い方(初期化)
・CoreCLR初期化
CoreCLRにpublishされたC#の.dllファイルパスを「:」区切りで
propertyValuesに一通りわたして初期化します
int hr = initializeCoreClr(
runtimePath, // App base path
"HostingOnPHP", // AppDomain friendly name
sizeof(propertyKeys) / sizeof(char*), // Property count
propertyKeys, // Property names
propertyValues, // Property values
&hostHandle, // Host handle
&domainId); // AppDomain ID
dotnet_ffiではPHPプロセスが作られるタイミングで初期化
PHP_MINIT_FUNCTION(dotnet_ffi)
CoreCLRの使い方(C#呼び出し)
・C#のメソッドの関数ポインタを取得
C#のプロジェクト名、名前空間までつけた完全修飾のクラス名、メソッド名とC#のクラスへ
のアドレスが格納されるポインタを渡す
*hr = createManagedDelegate (
hostHandle,
domainId,
target_project_name .c_str(),
target_class_name.c_str(),
method_name,
(void**)&managedDelegateInvokeReturnString);
・C#のメソッド呼び出し
std::string ret = managedDelegateInvokeReturnString(inStr);
この関数ポインタを実行することで
C#のメソッドを呼び出せる
CoreCLRの使い方(終了)
・C#のCoreCLRの終了
使い終わったらshutdown
dotnet_ffiではphpプロセスが作り直されるタイミングにあわせてシャットダウン
(VMの生成と初回JITコンパイルコストが高いので)
int hr = shutdownCoreClr(hostHandle, domainId);
dotnet_ffiではPHPのプロセスが終了するタイミング
PHP_MSHUTDOWN_FUNCTION(dotnet_ffi)
Extensionを作るための情報源
Extensionについての公式ドキュメント
公式のExtensionのドキュメントはない(2022年9月時点)
以前は「PHP のコア: ハッカーの手引き」という項目があったが無くなっている
それもPHP5.3.3頃で止まっている模様
検索しても非公式のミラーがいくつか引っ掛かる程度
(それもTLS対応していないサイトだったりする)
PHPのソースを追いましょう
現時点で一番確実なのはPHPのソースを追う
PHPのソースにあたることで下記の情報が得られる
・Extensionのひな形の作り方
・Extensionとしてのクラスや関数の宣言のしかた
・PHP用のconfig.m4の書き方
※ソースを追うときには使いたい PHPバージョンのタグを指定して追うのが安全
Extensionのひな形の作り方
そもそもどこからExtension開発に手を付けていいかがわかりづらいが
PHPのソース内のextディレクトリを探すと
ext_skel.phpというスクリプトがあり、これでひな形が作れる
https://github.com/php/php-src/blob/php-8.1.10/ext/ext_skel.php
php ext_skel.php --help
とするとExtensionのひな形の作り方やビルドのしかたがでてくる
Extensionのひな形の作り方
extension_exampleというExtensionを作る場合の例
php ext_skel.php --ext extension_example
cd extension_example
phpize
./configure
make
make test
※PECLでXMLを書いてひな形にする方法もあります
ここに作りたいExtension名を指定する
Extensionとしてのクラスや関数の宣言のしかた
旧公式ドキュメントでもExtensionの関数の宣言のやり方は載っていたが
Extensionとしてのクラスの宣言方法は載っていなかった
PHPの標準クラスで似たようなインターフェイスのクラスを探して
その書き方を参考にするのが楽
同じextディレクトリ内にあるので色々見てみると参考になる
(個人的にはSQLite3のクラスが一通りそろっていて参考になった)
PHP用config.m4の書き方
ライブラリのリンクのしかたなど、automakeから拡張されているものもある
例えばライブラリをstatic linkする際の書き方などは、ほかのExtensionを調べたほうが
確実(一番調べるのに苦労した)
例
PHP_ADD_LIBRARY_WITH_PATH("coreclr_ctlpp", $DOTNET_FFI_DIR/coreclrhost, EXTRA_LDFLAGS)
今後の展望
今後の展望
・.NET7への対応
.NET7自体が速度向上しているのもあり、
間接的なPHPの処理速度向上が期待できそう
・呼び出しメソッドを可変化
C#側のメソッド名をPHPから動的に指定して実行できるようにしたい
但し、パフォーマンスが若干犠牲になる可能性あるので慎重にゆきたい
(現在はiniで指定する形、一度見つけた関数ポインタは使いまわし)
・PHP8.2への対応
リリースされ次第対応予定
要望等お気軽にお寄せください
おまけ: エンジニア系Vtuberはじめました
Twitter
@SabanoIriko
Youtube 佐波野いりこチャンネル
https://www.youtube.com/channel/UCQoB5I4tj36wgcvzIQrjpVA
↑よろしければチャンネル登録
よろしくお願いします_(._.)_

More Related Content

Similar to PHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみた

PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjPhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjHisateru Tanaka
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterMasanori Oobayashi
 
Pinoco phptal-phpcon-kansai
Pinoco phptal-phpcon-kansaiPinoco phptal-phpcon-kansai
Pinoco phptal-phpcon-kansaiHisateru Tanaka
 
The History of Reactive Extensions
The History of Reactive ExtensionsThe History of Reactive Extensions
The History of Reactive ExtensionsYoshifumi Kawai
 
httpbis interim とhttp2.0相互接続試験の話
httpbis interim とhttp2.0相互接続試験の話httpbis interim とhttp2.0相互接続試験の話
httpbis interim とhttp2.0相互接続試験の話shigeki_ohtsu
 
php-timecopを実戦投入してみた
php-timecopを実戦投入してみたphp-timecopを実戦投入してみた
php-timecopを実戦投入してみたYoshio Hanawa
 
10分でわかるPythonの開発環境
10分でわかるPythonの開発環境10分でわかるPythonの開発環境
10分でわかるPythonの開発環境Hisao Soyama
 
私の好きなPython構文 vol.2 #nds46
私の好きなPython構文 vol.2 #nds46私の好きなPython構文 vol.2 #nds46
私の好きなPython構文 vol.2 #nds46civicpg
 
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情Junichi Ishida
 
[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform
[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform
[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform拓将 平林
 
C#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかC#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかYoshifumi Kawai
 
about Thrift
about Thriftabout Thrift
about ThriftNaoya Ito
 
Linux daemonとsupervisordの美味しい関係
Linux daemonとsupervisordの美味しい関係Linux daemonとsupervisordの美味しい関係
Linux daemonとsupervisordの美味しい関係Kazushige TAKEUCHI
 
初めてのWebプログラミング講座
初めてのWebプログラミング講座初めてのWebプログラミング講座
初めてのWebプログラミング講座DIVE INTO CODE Corp.
 
.NET Coreとツール類の今
.NET Coreとツール類の今.NET Coreとツール類の今
.NET Coreとツール類の今Yuki Igarashi
 
DLR言語によるSilverlightプログラミング
DLR言語によるSilverlightプログラミングDLR言語によるSilverlightプログラミング
DLR言語によるSilverlightプログラミングterurou
 
第2回関西ソーシャルゲーム勉強会
第2回関西ソーシャルゲーム勉強会第2回関西ソーシャルゲーム勉強会
第2回関西ソーシャルゲーム勉強会ha1t
 

Similar to PHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみた (20)

PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugjPhpStormを使おう --高槻からは快速急行が早くなります #jbugj
PhpStormを使おう --高槻からは快速急行が早くなります #jbugj
 
C#で速度を極めるいろは
C#で速度を極めるいろはC#で速度を極めるいろは
C#で速度を極めるいろは
 
WTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniterWTM53 phpフレームワーク いまさらcodeigniter
WTM53 phpフレームワーク いまさらcodeigniter
 
ゆるかわPhp
ゆるかわPhpゆるかわPhp
ゆるかわPhp
 
Pinoco phptal-phpcon-kansai
Pinoco phptal-phpcon-kansaiPinoco phptal-phpcon-kansai
Pinoco phptal-phpcon-kansai
 
The History of Reactive Extensions
The History of Reactive ExtensionsThe History of Reactive Extensions
The History of Reactive Extensions
 
httpbis interim とhttp2.0相互接続試験の話
httpbis interim とhttp2.0相互接続試験の話httpbis interim とhttp2.0相互接続試験の話
httpbis interim とhttp2.0相互接続試験の話
 
php-timecopを実戦投入してみた
php-timecopを実戦投入してみたphp-timecopを実戦投入してみた
php-timecopを実戦投入してみた
 
10分でわかるPythonの開発環境
10分でわかるPythonの開発環境10分でわかるPythonの開発環境
10分でわかるPythonの開発環境
 
私の好きなPython構文 vol.2 #nds46
私の好きなPython構文 vol.2 #nds46私の好きなPython構文 vol.2 #nds46
私の好きなPython構文 vol.2 #nds46
 
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
YAPC::Asia 2014 - 半端なPHPDisでPHPerに陰で笑われないためのPerl Monger向け最新PHP事情
 
[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform
[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform
[REV UP] あなたならどう使う?最新Azureレシピ for LINE Platform
 
C#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのかC#の強み、或いは何故PHPから乗り換えるのか
C#の強み、或いは何故PHPから乗り換えるのか
 
about Thrift
about Thriftabout Thrift
about Thrift
 
Linux daemonとsupervisordの美味しい関係
Linux daemonとsupervisordの美味しい関係Linux daemonとsupervisordの美味しい関係
Linux daemonとsupervisordの美味しい関係
 
初めてのWebプログラミング講座
初めてのWebプログラミング講座初めてのWebプログラミング講座
初めてのWebプログラミング講座
 
.NET Coreとツール類の今
.NET Coreとツール類の今.NET Coreとツール類の今
.NET Coreとツール類の今
 
DLR言語によるSilverlightプログラミング
DLR言語によるSilverlightプログラミングDLR言語によるSilverlightプログラミング
DLR言語によるSilverlightプログラミング
 
Thrift
ThriftThrift
Thrift
 
第2回関西ソーシャルゲーム勉強会
第2回関西ソーシャルゲーム勉強会第2回関西ソーシャルゲーム勉強会
第2回関西ソーシャルゲーム勉強会
 

PHPからC#のライブラリを呼べるようにしたdotnet_ffiを趣味でつくってみた