ホームページ  >  記事  >  バックエンド開発  >  PHPのFFIを使用してcjiebaを呼び出す

PHPのFFIを使用してcjiebaを呼び出す

藏色散人
藏色散人転載
2020-11-19 15:21:404135ブラウズ

推奨: 「PHP ビデオ チュートリアル

phpjieba_ffi

PHP 7.4 の FFI テストを使用して、直接call cjieba Word セグメンテーション ダイナミック ライブラリ

CJieba を選択した理由は、FFI が C 呼び出し規約を使用しているためです。Cpp を使用する場合は、それを自分でパッケージ化し、コンパイラに標準 C を生成させるために C を extern する必要があります。ダイナミックライブラリ。

発生した問題

セグメンテーション違反

C 変数が初期化されていません

C が直接呼び出されますFFI

によって初期化された C オブジェクトによって関数が呼び出されない

ポインタ形式での配列のループ

C コードを見ると、Cut 部分は次のようになっていることがわかりました。

CJiebaWord* Cut(Jieba handle, const char* sentence, size_t len) {
  cppjieba::Jieba* x = (cppjieba::Jieba*)handle;
  vector<string> words;
  string s(sentence, len);
  x->Cut(s, words);
  
  CJiebaWord* res = (CJiebaWord*)malloc(sizeof(CJiebaWord) * (words.size() + 1));
  size_t offset = 0;
  for (size_t i = 0; i < words.size(); i++) {
    res[i].word = sentence + offset;
    res[i].len = words[i].size();
    offset += res[i].len;
  }
  if (offset != len) {
    free(res);
    return NULL;
  }
  res[words.size()].word = NULL;
  res[words.size()].len = 0;
  return res;
}

返されるのは構造体です。ポインタ。C 言語では、配列名は実際には配列内の最初の変数のポインタ アドレスなので、ポインタ アドレスの操作を通じて調べることができます。FFI ではどうですか?

この配列では、最初は foreach ループを使用し、セグメンテーション エラーを直接報告しました。その後、C のようなポインターを直接使用して、それが実行可能であることがわかりました。FFI に高く評価します。 C ポインタを操作します。

単語分割結果の取得

上記のコードに示すように、単一の単語分割 CJiebaWord の場合、保存された単語分割ではなく、センテンス オフセットです。これは、最初の単語の分割結果が生の文字列であることが確実であることを意味します。

C デモでは、printf フォーマット (. はフィールド幅と配置を示します) ですが、PHP には同様のメソッドがありません。文字列 substr($x->word, 0, をインターセプトする必要があります) $x- >len)

  for (x = words; x->word; x++) {
    printf("%*.*s\n", x->len, x->len, x->word);
  }

使用例

動的ライブラリのコンパイル

make libjieba.so
実行
time php demo.php

C デモを実行します

make demo
time ./demo

結果

PHP
load: 0.00025701522827148
real    1m59.619s
user    1m56.093s
sys     0m3.517s
C
real    1m54.738s
user    1m50.382s
sys     0m4.323s
CPU 占用 基本都是 12%

FFI を使用すると、PHP の速度は基本的に C と同じであることがわかります。 CPU では、他の言語 (C/C、golang、Rust など) を使用して、標準 C ダイナミック ライブラリを作成してエクスポートしてみることができます。

FFI の使用

システム コールまたは SDK コールが必要だった FFI が登場する前は、PHP で拡張機能を開発する必要がありましたが、拡張機能の開発には、 C 言語を使用しても、PHP カーネルを理解する必要がありますが、これはより困難です。 FFI を直接使用してダイナミック ライブラリを呼び出すことができるようになり、さらに便利になりました。

拡張マクロ拡張

たとえば、Hikvision の SDK には多数のマクロがあります。 gcc -E -P HCNetSDK.h -o HCNetSDK_unfold.h は型定義をサポートしています。 、お気軽にお使いください

元のアドレス: https://github.com/dwdcth/phpjieba_ffi

以上がPHPのFFIを使用してcjiebaを呼び出すの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はgithub.ioで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。