Top View


Author shiro seike / せいけ しろう / 清家 史郎

php-ffiを利用してcgoで作った関数を実行する

2021/09/09

php-ffiのインストール

最近社内記事で知ったasdfを利用してffiを入れていきます。 環境はMacです。

# PHPのconfigure_optionを設定

$ export PHP_CONFIGURE_OPTIONS="--with-ffi --with-iconv=/usr/local/opt/libiconv --with-openssl=/openssl@1.1@"

# 7.4.22をインストール

$ asdf install php 7.4.22

# 利用するPHPを7.4.22に切替

$ asdf glonal php 7.4.22

# モジュールがインストールされているかを確認

$ php -m | grep FFI
FFI

php-ffiが入りました。

php-ffiにてサンプルを実行する

実際にC言語のサンプルを動かします。
サンプルはLinux向けなので、ここではDockerで動かしてしまいます。

ffiが入ったDockerイメージを通して以下phpを実行

<?php
// create FFI object, loading libc and exporting function printf()
$ffi = FFI::cdef(
    "int printf(const char *format, ...);", // this is a regular C declaration
    "libc.so.6");
// call C's printf()
$ffi->printf("Hello %s!\n", "world");

$ docker run -it --rm -v "$PWD":/tmp -w /tmp php-ffi php BasicFFIusage.php
Hello world!

cgoを利用した共有ライブラリを作成する

以下の様なコードを書きます。
その際にexport 〇〇 といったコメントを書く事で外部から利用出来るようにします

package main

import "C"

//export add ※add関数をexport
func add(i int, n int) int {
        return i + n
}

//export minus ※minus関数をexport
func minus(i int, n int) int {
        return i - n
}

func main() {}

共有ライブラリとしてBuildします。

Macようなので名前は念の為dylibとします。

$ go build -buildmode=c-shared -o seike460.dylib seike460.go

共有ライブラリをphp-ffiで読み込んで実行します

<?php
// 第1引数に利用する関数の宣言、第2引数に読み込む共有ライブラリ
$ffiGo = \FFI::cdef(
    'extern int add(int p0, int p0);
     extern int minus(int p0, int p0);',
    'seike460.dylib'
);

echo $ffiGo->add(3, 2) . PHP_EOL;
echo $ffiGo->minus(3, 2) . PHP_EOL;

このファイルを実行すると、なんと足し算と引き算が出来ます。

$ php ffi.php
5
1

文字列や配列などを扱うのは一工夫必要で、
調査してたところ非常に有用な記事がありましたので合わせて紹介致します。

hanhan's blog

まとめ

PHPとGoを使ってる身としてPHPからGoを使うことで速度的な優位製を 表現力の高いPHPでかけることは使いみちとしてなくはないなと感じました。

またC共有ライブラリのこの関数を使いたい…!というときでも使えるので、 興味があれば試してみてください。

shiro seike / せいけ しろう / 清家 史郎

shiro seike / せいけ しろう / 清家 史郎

Twitter X

Company:Fusic CO., LTD. Slides:slide.seike460.com blog:blog.seike460.com Program Language:PHP , Go Interest:Full Serverless Architecture