php調用c函數
⑴ php底層原理 php是如何運行的
1、PHP動態語言執行過程:拿到一段代碼後,經過詞法解析、語法解析等階段後,源程序會被翻譯成一個個指令(opcodes),然後ZEND虛擬機順次執行這些指令完成操作。PHP本身是用C實現的,因此最終調用的也是C的函數,實際上,我們可以把PHP看做一個C開發的軟體。
2、PHP的4層運行體系:
(1)Zend引擎:Zend整體用純C實現,是PHP的內核部分,他將PHP代碼翻譯(詞法、語法解析等一系列編譯過程)為可執行opcode的處理並實現相應的處理方法、實現了基本的數據結構(如:hashtable、OO)、內存分配機制及管理、提供了相應的api方法供外部調用,是一切的核心,所有的外圍功能均圍繞Zend實現。
(2)Extensions:圍繞著Zend引擎,extensions通過組件式的方式提供各種基礎服務,我們常見的各種內置函數(array系列)、標准庫等都是通過extension來實現,用戶也可以根據需要實現自己的extension的典型應用)。
(3)Sapi:Sapi全稱,也就是服務端應用編程介面,Sapi通過一系列鉤子函數,使得PHP可以和外圍交互數據,這是PHP非常優雅和成功的設計,通過sapi成功的將PHP本身和上層應用解耦隔離,PHP可以不再考慮如何針對不同應用進行兼容,而應用本身也可以針對自己的特點實現不同的處理方式。
(4)上層應用:這就是我們平時編寫的PHP程序,通過不同的spai方式得到各種各樣的應用模式,如何通過webserver實現web應用、在命令行下已腳本方式運行等等。
⑵ 用PHP編寫的一行行代碼 是怎麼在伺服器端運行的
從圖上可以看到,PHP實現了一個典型的動態語言執行過程:拿到一段代碼後,經過詞法解析、語法解析等階段後,源程序會被翻譯成一個個指令 (opcodes),然後ZEND虛擬機順次執行這些指令完成操作。PHP本身是用C實現的,因此最終調用的也都是C的函數,實際上,我們可以把PHP看 做是一個C開發的軟體。
PHP的執行的核心是翻譯出來的一條一條指令,也即opcode。
Opcode是PHP程序執行的最基本單位。一個opcode由兩個參數(op1,op2)、返回值和處理函數組成。PHP程序最終被翻譯為一組opcode處理函數的順序執行。
常見的幾個處理函數:
1 ZEND_ASSIGN_SPEC_CV_CV_HANDLER : 變數分配 ($a=$b)
2 ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER:函數調用
3 ZEND_CONCAT_SPEC_CV_CV_HANDLER:字元串拼接 $a.$b
4 ZEND_ADD_SPEC_CV_CONST_HANDLER: 加法運算 $a+2
5 ZEND_IS_EQUAL_SPEC_CV_CONST:判斷相等 $a==1
6 ZEND_IS_IDENTICAL_SPEC_CV_CONST:判斷相等 $a===1
⑶ php能夠調用C或C++寫的.dll文件嗎 - PHP進階討論
可以我寫過一個調用SAP BO的COM,要調用必須先安裝好COM組件的,在注冊表查出組件名字(如果你不清楚組件名字的話)我把我寫過的函數給你看看
/**
* 載入COM組件
*/
private function createCompanyObject() {
$company = false;
try {
$company = new COM("SapBobsCom.Company");//這樣就可以獲取COM組件了
} catch(Exception $e) {
$this->errorMsg = $e->getMessage();
}
return $company;
}
⑷ php如何調用函數
PHP函數調用與Java/C/C++是一樣的額,通過函數名(參數列表)就可以了,
舉個栗子:
圖中,有兩處函數調用,一開始的session_start()是調用的PHP函數,validate_user($username, $password)是用戶自定義函數,同樣的方式調用。
⑸ PHP中通過Web 執行C/C++應用程序
一、簡介
如果你對Unix/Linux有所了解的話,你應該知道他們大都自帶了C和C++的編譯器,分別是GCC和G++。Unix在程序安裝及Make等許多地方使用到了這戚圓些編譯器。利用一些控制台命令,C++和PHP, 我將向你介紹怎樣生成一個完整的C++程序例子,他可以在用PHP程序來執行,並能獲得相應的輸出結果。我將先生成C++程序代碼,並編譯它,談後討論我們將如果通過使用PHP的函數passthru來執行這個程序。從某種意義上來說,這邊文章給我們提供一種通過Web頁面來訪問一般程序的方法。
為了能更好的理解這篇文章,你應該有一台運行著apache和最新版本php的unix/Linux伺服器。同時也應該掌握C++, unix控制台命令,當然一些PHP的編程經驗也是必需的。
二、編寫一個C++程序
例如,我們可以寫一個能夠通過命令行還接收參數的C++ 簡單程序,並命名為Sampleapp.然後我們能夠按照下面的方式給他傳遞三個不同的參數 :
Sampleapp ?參高凳塌數一 ?參數二 ?參數三
這個程序的功能是能輸出傳遞給他的參數的個數和每個參數的值,然後我們可以用PHP腳本程序來執行編譯好的C++程序。
利用你習慣的文本編輯器,新建一個名為Sampleapp.cpp 的文件,再此文件中輸入如下的代碼:
#include
int main(int argc, char* argv[])
{
cout
endl
"You passed "
argc-1
" arguement"
(argc-1 == 1 ? "" : "s")
"."
endl;
cout
(argc-1 == 1 ? "This" : "These")
" arguement"
(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;
}
這個C++程序包含的程序的入口點:main(),main()函數帶了兩個參數:argc(命令行傳入參數的個數)和argv(一個包含了所傳參數實際值的字元型指針數組)。這個兩個參數能被C++編譯器自動捕獲。
cout
endl
"You passed "
argc-1
" arguement"
(argc-1 == 1 ? "" : "s")
"."
endl;;
這句話的意思是獲得從執行命令行傳入的參數的個數。Argv這個字元型指針數組是從0開始檢索的,它至少包含一個實際的值(即本程序的路徑和名稱),這個值由C++編譯器自動地附加上去。條件操作符」?」是用來判斷命粗升令行傳入地參數是否多於一個。例如,如果命令行過傳入兩個參數,我們地程序將輸出如下信息:
You passed 2 arguments.
cout
(argc-1 == 1 ? "This" : "These")
" arguement"
(argc-1 == 1 ? "" : "s")
" "
(argc-1 == 1 ? "is" : "are")
": "
endl
endl;
接下來,我們同樣用條件操作符來輸出另一句話。不過要記住,即使我們不從程序執行命令行傳入任何參數,main函數地argv[]參數也包含一個值。同樣地,如果我們從命令行傳入兩個參數給程序,程序將輸出如下地信息:
These arguments are:
for(int i = 1; i
argc; i++)
cout
"["
i
"] "
argv[i]
endl;
最後,main函數逐一的輸出命令行傳入的每個參數,它用到了一個簡單的for(;;)循環語句,這個函數能根據參數的個數將參數值一個一個的輸出。假如我們傳給程序兩個參數」first」和second」, for循環輸出的結果如下:
[1] ?first
[2] ?second
接下來,我們將編譯這個.cpp文件,如果你在Windows平台下,需要telnet到所使用的server上。在這里,我們使用大多Unix機器上都提供的G++編譯器來編譯這個源文件。不過為了確信你的機器安裝了G++,你可以輸入如下命令:which g++。如果G++已經安裝了,Unix shell將顯示出G++所在的全路徑。如果沒有安裝,它將提示你說」command couldn』t be found」. 你可以在這里下載到G++.
在源文件所在的目錄輸入如下G++命令:
g++ -c sampleapp.cpp.
通過這個命令,我們就將. cpp文件編譯成了包含機器代碼的目標文件。通過 ls ?a命令,你可以發現在本目錄下出現了一個新文件sampleapp.o,這就是.cpp源文件被編譯成機器碼的結果。不過我們最終想要的是一個可執行文件,因為我們還要輸入如下的G++命令:
g++ sampleapp.cpp ?o sampleapp
這樣我們就獲得了一個名為sampleapp的可執行文件。不過注意的是,Unix下的可執行文件跟Windows不一樣,它沒有任何後綴。
下面我們可以來檢驗一下程序執行的結果,如果如下命令:
sampleapp one -two /three
我們可以看到如下的執行結果:
You passed 3 arguments.
These arguments are:
[1] one
[2] ?two
[3] /three
現在,可執行的C++程序成生完畢,下面我們將生成一個能夠通過 web瀏覽器來訪問這個程序的PHP教本程序。
三、生成PHP腳本程序
為了能通過Internet來調用我們的C++程序,我們需要生成一個PHP腳本程序。這個PHP腳本程序將有一個Form表單,以便用戶能輸入可以傳給程序Sampleapp的參數。PHP腳本的代碼太長就不在這里全部列出了,需要的話可以通過下面的地址來下載它。(Php code)
if(@$submit)
{
}
else
{
}
#p#副標題#e#
首先,腳本程序檢查看變數$submit是否有值,這個變數$submit的值是程序後面的Form表單提交後傳遞過來的,它預設為空值。符號@的作用是當變數$submit的值不存在的時忽略相關的錯誤信息。
由於變數$submit預設為空,所以一開始執行else{}中的代碼,它在瀏覽器上簡單的顯示一個Form表單。Form的action屬性設為變數 $PHP_SELF,即表單提交後返回本頁。同時Form表單包含了一個文本輸入條,這是用來讓用戶輸入要傳遞給C++程序的命令行參數。Form如下圖所示:
一旦我們輸入執行命令並提交表單,變數$submit(即按鈕Go的名字)就獲得一個值,這樣PHP教本將執行if{}之間的代碼。
if($args == "")
echo " You didn't enter any arguments.";
else
{
echo " SampleApp Result";
$command = "/htdocs/sampleapp " . escapeshellcmd($args);
passthru($command);
}
變數$args是自動產生的,它的值是Form表單中文本輸入條傳過來的值。如果沒有輸入任何信息,程序將簡單的告訴用戶沒有輸入任何值。
如果用戶輸入任何非空的信息,程序將把text域的值,即變數$args傳給C++程序。下面這段代碼就是執行C++的程序的執行命令:
$command = "/htdocs/sampleapp " . escapeshellcmd($args);
函數eacapeshellcmd是用來當做安全檢查工具,以過濾調一些如」,」,」」和」」等的特殊字元。這可以防止一些用戶企圖輸入某些字元來調用系統內部命令。
例如,如果你在Form表單的text域中輸入」1 ?two /three」,那麼變數$command的值就為: /htdocs/sampleapp 1 ?two /three
你能發現我們定義了程序sampleapp的全路徑,在這個例子中,程序文件位於/htdocs目錄下。你可以根據的自己程序所在的目錄做相應的修改。
passthru($command);
最後,我們使用PHP的函數passthru來執行變數$command所包含的命令並且將原始的執行結果輸出到瀏覽器上。在我的伺服器上,返回結果的HTML頁面如下:
w在本文即將結束之前,幾個可能碰到的問題我想說一下。首先,當你執行sampleapp.php教本程序的時候,如果你沒有看到程序的任何輸出信息,或許是開了安全模式。如果這樣,系統將不會允許PHP腳本來執行系統內部程序。其次,在一些Unix系統上,PHP函數passthru不能將內部程序的輸出傳遞給瀏覽頁面,如果發生這種情況,可以用system函數來代替passthru函數。
四、結論
從本的例子可以看出,Unix操作系統非常強大,並且PHP允許開發者通過腳本以獨立的線程來執行系統內部程序。本文的所給的例子非常的簡單,但是只要再多花一點功夫,你可以寫一個能更新Mysql資料庫的c++程序,運行其他系統命令的程序或者是操作系統文件/目錄結構的程序。但是,不管怎樣,你都應該確保你的系統安全,絕對不能讓任何其他的腳本程序隨意訪問系統內部程序。
#p#副標題#e#
⑹ php語言可執行c語言么
不能啊,PHP 跟C有各自運行的伺服器,雖然說PHP是建立在C的基礎上的,但是兩者不可能相通的,不過可能會有高手知道,
⑺ C++的標准動態庫為什麼不能被PHP調用
php調用C/C++動態鏈接庫
一、簡介
一般而言,php速度已經比較快,但是,對於一些較高級開發者而言,如果想要追求更快的速度,那毫無疑問可以通過自己寫c代碼,並編譯為動態鏈接庫(常為.so文件),然後php通過創建一個新的擴展(extension),並在擴展里調用該.so文件,同時對外暴露出php函數介面。
在實際使用中,只要調用該函數介面,即可使用底層更快速的c函數服務。
二、起因
之所以本人要研究這么個問題,主要是近來項目中需要調用一個自己開發的圖像處理的動態鏈接庫,希望伺服器能夠對客戶端提供該圖像處理服務。而我們伺服器開發語言選擇了php,所以著手此問題。
三、實現方法
廢話不多說,為了實現php調用c庫,我在網上搜了個遍也沒找到幾篇好文章,只有兩篇還不錯的,分享在本文最末,有興趣的讀者可以去閱讀。
下面,本文的開發環境背景是CentOS release 6.5 。為了能夠調用c庫,我們的php 5.6.9,apache 2.4均是下載源碼並編譯的,不可直接通過yum安裝!請注意。至於php和apache的源碼編譯本文不提,只要注意在configure打開合適開關即可。
具體步驟如下:
將共享庫.so添加入系統配置中(假設共享庫名為 'libhello.so')
cp libhello.so /usr/local/lib
echo /usr/local/lib > /etc/ld.so.conf.d/local.conf
/sbin/ldconfig
在php/ext目錄下創建擴展頭文件,取名為myfunctions.def
在該文件里填寫c函數聲明即可。每個函數一行。
string hello(int a)
int hello_add(int a, int b)
使用ext_skel搭建擴展骨架
./ext_skel --extname=myfunctions --proto=myfunctions.def
打開config.m4 中的enable開關
PHP_ARG_ENABLE(myfunctions, whether to enable myfunctions support,
[ --enable-myfunctions Include myfunctions support])
上面把擴展骨架建立好了,下面重新配置php (下面是我個人配置文件,讀者需要結合自己情況修改)
./buildconf --force //生成新配置腳本
'./configure' '--prefix=/usr/local/php' '--with-libdir=lib64' '--enable-fpm' '--with-fpm-user=php-fpm' '--with-fpm-group=www--enable-mysqlnd' '--with-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--with-pdo-mysql=mysqlnd' '--enable-opcache' '--enable-pcntl' '--enable-mbstring' '--enable-soap' '--enable-zip' '--enable-calendar' '--enable-bcmath' '--enable-exif' '--enable-ftp' '--enable-intl' '--with-openssl' '--with-zlib' '--with-curl' '--with-gd' '--with-zlib-dir=/usr/lib' '--with-png-dir=/usr/lib' '--with-jpeg-dir=/usr/lib' '--with-gettext' '--with-mhash' '--with-ldap' '--disable-fileinfo' '--with-config-file-path=/usr/local/php/etc' '--with-apxs2=/usr/local/httpd/bin/apxs' '--enable-myfunctions' // 配置
記住!一定在末尾加上 —enable-myfunctions 。這樣子才會被編譯進php中。
當擴展編譯進去了之後,就可以開始修改擴展里的myfunctions.c文件,在裡面可以添加php->c的轉接函數,在轉接函數里可以調用.so內的函數。
比如要添加一個hello_add的php函數,裡面可以調用c函數add(int a, int b)
a. 添加函數聲明
PHP_FE(hello_add, NULL)
b. 添加php函數
PHP_FUNCTION(hello_add){ ... }
注意,在該函數里,如果調用了.so文件里的介面函數,那麼待會在make的時候,要指定所使用的.so共享庫,該共享庫必須完成第1步中添加到系統配置的操作。
如果調用了.so文件,那麼要在php/Makefile中添加
Extra_LDFLAG = -lhello //對應前面的libhello.so
Extra_libs = -lhello
(make clean)
每次修改完上面的c文件,都要重新make
make
make install
重啟apache伺服器
httpd -k restart
在phpinfo里可以看到新擴展,可以直接在php調用新擴展內的函數。
⑻ php調用自定義函數
PHP代碼call_user_func函數類似於一種特別的調用函數的方法,使用方法如下:
function
a($b,$c)
{
echo
$b;
echo
$c;
}
call_user_func('a',
"111","222");
call_user_func('a',
"333","444");
//顯示
111
222
333
444
?>
調用類內部的方法比較奇怪,居然用的是array,不知道開發者是如何考慮的,當然省去了new,也是滿有新意的:
class
a
{
function
b($c)
{
echo
$c;
}
}
call_user_func(array("a",
"b"),"111");
//顯示
111
?>
call_user_func_array函數和call_user_func很相似,只不過是換了一種方式傳遞了參數,讓參數的結構更清晰:
function
a($b,
$c)
{
echo
$b;
echo
$c;
}
call_user_func_array('a',
array("111",
"222"));
//顯示
111
222
?>
call_user_func_array函數也可以調用類內部的方法的
Class
ClassA
{
function
bc($b,
$c)
{
$bc
=
$b
+
$c;
echo
$bc;
}
}
call_user_func_array(array('ClassA','bc'),
array("111",
"222"));
//顯示
333
?>
call_user_func函數和call_user_func_array函數都支持引用,這讓他們和普通的函數調用更趨於功能一致:
function
a($b)
{
$b++;
}
$c
=
0;
call_user_func('a',
$c);
echo
$c;//顯示
1
call_user_func_array('a',
array($c));
echo
$c;//顯示
2
另:call_user_func函數和call_user_func_array函數都支持引用。
?phpfunction
increment(&$var){
$var++;}$a
=
0;call_user_func('increment',
$a);echo
$a;
//
0call_user_func_array('increment',
array(&$a));
//
You
can
use
this
insteadecho
$a;
//
1?