首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 呼叫 C 程式碼三大方案:系統呼叫、Daemon 通訊與編寫擴展完整比較

     編輯:PHP 相關知識

當 PHP 效能不足或需複用既有 C 程式庫時,有三種整合路徑。本文從架構、效能、開發成本三面向比較,並完整示範「編寫 PHP 擴展」的標準流程。

三大方案快速比較

方案適用場景效能複雜度維護性
1. system()/exec() 呼叫獨立執行檔既有 CLI 工具、低頻任務、隔離崩潰風險低 (進程啟動開銷大)低高 (語言無關)
2. C Daemon + Socket/IPC高頻、長連線、狀態保持、多語言共用中高 (避免重啟)高 (需處理通訊協定、併發)中
3. PHP C 擴展高頻運算、需共享記憶體、深度整合 Zend最高 (內嵌執行)中高 (需懂 Zend API)中 (隨 PHP 部署)

方案三:編寫 PHP 擴展完整步驟 (以 hello 為例)

1. 產生骨架

cd php-src/ext
./ext_skel --extname=hello
# 產生 hello/ 目錄,關鍵檔:config.m4, hello.c, php_hello.h

2. 修改 config.m4 啟用 --with-hello

# 將 PHP_ARG_WITH 區塊取消註解
PHP_ARG_WITH(hello, for hello support,
[  --with-hello             Include hello support])

3. 編譯安裝

cd hello
phpize
./configure --with-hello
make
# 產生 modules/hello.so

4. 動態載入 (不修改 php.ini)

<?php
function dl_local(string $so): string {
    if (!ini_get('enable_dl') || ini_get('safe_mode')) die('dl disabled');
    $path = __DIR__ . '/' . $so;
    if (!is_file($path) || !is_executable($path)) die("invalid $so");
    if (!dl($path)) die('load failed');
    return end(get_loaded_extensions());
}

if (!extension_loaded('hello')) dl_local('hello.so');
hello_world(); // 呼叫擴展函式
?>

5. 實作函式:參數解析與回傳值

// hello.c
#include "php_hello.h"

ZEND_FUNCTION(hello_strdiff) {
    char *s1, *s2;
    size_t l1, l2;
    // 參數解析:"ss" = 兩個字串
    if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &s1, &l1, &s2, &l2) == FAILURE) return;

    // 計算 Levenshtein 距離 (示範演算法)
    int n = l1, m = l2;
    int *d = ecalloc((n+1)*(m+1), sizeof(int));
    for (int i=0;i<=n;i++) d[i*(m+1)] = i;
    for (int j=0;j<=m;j++) d[j] = j;
    for (int i=1;i<=n;i++) {
        for (int j=1;j<=m;j++) {
            int cost = (s1[i-1]==s2[j-1]) ? 0 : 1;
            int a = d[(i-1)*(m+1)+j] + 1;
            int b = d[i*(m+1)+j-1] + 1;
            int c = d[(i-1)*(m+1)+j-1] + cost;
            d[i*(m+1)+j] = a < b ? (a < c ? a : c) : (b < c ? b : c);
        }
    }
    RETVAL_LONG(d[n*(m+1)+m]);
    efree(d);
}

// 註冊函式
zend_function_entry hello_functions[] = {
    ZEND_FE(hello_strdiff, NULL)
    ZEND_FE_END
};

Zend 參數/回傳宏速查

型別參數規格字元C 變數回傳宏
布林bzend_boolRETURN_BOOL
整數lzend_longRETURN_LONG
浮點ddoubleRETURN_DOUBLE
字串schar*, size_tRETURN_STRING(str, copy)
陣列/物件/資源a/o/rzval*RETURN_ZVAL

可選參數用 | 分隔,如 "s|l" 表字串 + 可選長整數。

記憶體管理關鍵

  • 使用 emalloc/ecalloc/erealloc/efree (請求生命週期自動釋放)。
  • 持久記憶體 (跨請求) 用 pemalloc(ptr, 1)。
  • 字串複製用 estrdup/estrndup,回傳時 RETURN_STRING(str, 0) 移交所有權。

效能實測參考

同一演算法:純 PHP → C 擴展 約 **90 倍** 提升;純 PHP → 獨立 C 程式 + exec() 約 **500 倍** (但含進程開銷)。擴展適合「高頻、小資料、低延遲」場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved