當需要高效能運算、呼叫現有 C/C++ 函式庫、或存取底層硬體時,可將核心邏輯寫成 C/C++ 可執行檔,再由 PHP 透過 passthru()、exec() 或 proc_open() 呼叫,實現 Web 介面操作系統級程式。
範例 SampleApp.cpp 接收命令列參數並回顯:
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
cout << endl << "You passed " << argc-1
<< " argument" << (argc-1 == 1 ? "" : "s") << "." << endl;
cout << (argc-1 == 1 ? "This" : "These")
<< " argument" << (argc-1 == 1 ? "" : "s")
<< " " << (argc-1 == 1 ? "is" : "are") << ": " << endl << endl;
for (int i = 1; i < argc; i++) {
cout << "[" << i << "] " << argv[i] << endl;
}
return 0;
}
編譯:
g++ SampleApp.cpp -o SampleApp
測試:
./SampleApp first second
# 輸出:
# You passed 2 arguments.
# These arguments are:
# [1] first
# [2] second
<?php
$args = escapeshellarg($arg1) . ' ' . escapeshellarg($arg2);
$cmd = "./SampleApp $args";
// 方法 1:passthru 直接輸出到瀏覽器
header('Content-Type: text/plain; charset=utf-8');
passthru($cmd, $return_var);
// 方法 2:exec 取得最後一行
// $output = [];
// exec($cmd, $output, $return_var);
// echo implode("\n", $output);
// 方法 3:proc_open 雙向溝通(進階)
// $proc = proc_open($cmd, [['pipe','r'],['pipe','w'],['pipe','w']], $pipes);
// ...
?>
escapeshellarg() 包裹每個參數,防指令注入proc_open 搭配 stream_set_timeout 防止阻塞ulimit 或 cgroups 限制 CPU/記憶體| 方案 | 優點 | 缺點 |
|---|---|---|
| PHP 擴充模組 | 效能最佳、型別安全 | 開發門檻高、需重編譯 PHP |
| FFI (PHP 7.4+) | 無需編譯擴充、直接呼叫 C 函式 | 僅支援簡單資料型別、效能稍遜 |
| gRPC / Message Queue | 解耦、跨語言、可水平擴展 | 架構複雜、延遲較高 |
| CLI 呼叫 (本文) | 快速原型、重用既有程式 | 進程開銷大、安全風險高 |