1. 程式人生 > >在Windows下用C擴充套件PHP(打包成dll)的方法

在Windows下用C擴充套件PHP(打包成dll)的方法

1、目的

為了在php中使用C語言的擴充套件,本文介紹在windows系統下,將C擴充套件打包成dll檔案,提供給php呼叫的方法

Linux系統下的方法見:http://c.biancheng.net/cpp/html/1400.html

2、需要安裝的軟體

(1)wamp server:其中包含php,本文中php版本為5.5.12

安裝路徑如:C:\wamp\,其中C:\wamp\bin\php\php5.5.12為php所在路徑,將其加入環境變數Path

(2)Visual Studio:本文中版本為VS2013

安裝路徑如:C:\Program Files (x86)\Microsoft Visual Studio 12.0\

將C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin; 和 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE; 加入環境變數Path

否則之後會報找不到C編譯器的錯誤:MS C++ compiler is required

(3)Cygwin:本文中版本為2.738,為了在windows下模擬unix環境,下載及安裝流程見:http://www.cr173.com/soft/60977.html

3、下載未編譯的php原始碼包

官方下載地址:http://www.php.net/downloads.php,選擇適當的版本和下載點下載,本文用的版本是5.5.26

下載後解壓原始碼包,找到./ext目錄,這個是負責開發擴充套件的目錄,有兩個主要用到的檔案,ext_skel,ext_skel_win32.php,

ext_skel是建立擴充套件的shell,在windows上無法執行,所以要有Cygwin

下載後,將安裝目錄下的所有原始碼檔案拷貝到C:\wamp\bin\php\php5.5.12\下

4、修改Cygwin路徑

如果你的Cygwin沒有安在c:\cygwin,進入./ext目錄下,修改ext_skel_win32.php

將$cygwin_path = 'c:\cygwin\bin';

修改為你的cygwin安裝目錄

5、寫C語言函式宣告檔案

在ext目錄下新建函式宣告檔案,如:myfunc.def

檔案內宣告C語言擴充套件對php提供的函式原型,如:

int a(int x,int y)
string b(string x, string y)

寫宣告檔案的目的是在下一步建立骨架目錄時,目錄內的.c檔案內會生成相應函式的部分程式碼,方便後續編寫。

這一步也可以省略,那麼需要在第7步新增額外的程式碼

6、建立php擴充套件骨架目錄

開啟Cygwin,cd到ext目錄c:/wamp/bin/php/php5.5.12/ext,根據myfunc.def建立骨架目錄:

php ./ext_skel_win32.php --extname=myfunc --proto=myfunc.def

若沒有生成def檔案,不需要最後一個引數

若報這個錯:
Warning: fopen(myhello/myhello.dsp): failed to open stream: No such file or directory in D:\cygwin\php-5.2.6\ext\ext_skel_win32.php on line 45 
Warning: fopen(myhello/myhello.php): failed to open stream: No such file or directory in D:\cygwin\php-5.2.6\ext\ext_skel_win32.php on line 52 

說明Cygwin安裝不完整,或者命令有錯,或者是目錄下已經有myfunc檔案夾了。檢查是否是上述錯誤後,重啟cygwin再試試。

若執行報錯php不是系統命令,將php所在路徑C:\wamp\bin\php\php5.5.12加入環境變數Path並重啟

執行成功顯示以下資訊:

$ php ./ext_skel_win32.php --extname=myfunc --proto=myfunc.def
Creating directory myfunc
awk: /cygdrive/c/wamp/bin/php/php5.5.12/ext/skeleton/create_stubs:56: w
scape sequence `\|' treated as plain `|'
Creating basic files: config.m4 config.w32 .svnignore myfunc.c php_myfu
ITS EXPERIMENTAL tests/001.phpt myfunc.php [done].


To use your new extension, you will have to execute the following steps


1.  $ cd ..
2.  $ vi ext/myfunc/config.m4
3.  $ ./buildconf
4.  $ ./configure --[with|enable]-myfunc
5.  $ make
6.  $ ./sapi/cli/php -f ext/myfunc/myfunc.php
7.  $ vi ext/myfunc/myfunc.c
8.  $ make


Repeat steps 3-6 until you are satisfied with ext/myfunc/config.m4 and
step 6 confirms that your module is compiled into PHP. Then, start writ
code and repeat the last two steps as often as necessary.

7、新增C語言程式碼

修改ext/myfunc/myfunc.c檔案,修改PHP_FUNCTION(a)和PHP_FUNCTION(b):

PHP_FUNCTION(a)
{
	int argc = ZEND_NUM_ARGS();
	long x;
	long y;

	if (zend_parse_parameters(argc TSRMLS_CC, "ll", &x, &y) == FAILURE) 
		return;
	
	int z = x+y;
	RETURN_LONG(z);
	//php_error(E_WARNING, "a: not yet implemented");
}
/* }}} */

/* {{{ proto string b(string x, string y)
   ; */
PHP_FUNCTION(b)
{
	char *x = NULL;
	char *y = NULL;
	int argc = ZEND_NUM_ARGS();
	int x_len;
	int y_len;

	if (zend_parse_parameters(argc TSRMLS_CC, "ss", &x, &x_len, &y, &y_len) == FAILURE) 
		return;
	
	int result_length = x_len + y_len;
	char* result = (char *) emalloc(result_length + 1);
	strcpy(result, x);
	strcat(result, y);

	RETURN_STRINGL(result, result_length, 0);

	//php_error(E_WARNING, "b: not yet implemented");
}



其中C函式返回值需要使用巨集,返回值型別對應的巨集如下表所示:
設定返回值並且結束函式 設定返回值 巨集返回型別和引數
RETURN_LONG(l) RETVAL_LONG(l) 整數
RETURN_BOOL(b) RETVAL_BOOL(b) 布林數(1或0)
RETURN_NULL() RETVAL_NULL() NULL
RETURN_DOUBLE(d) RETVAL_DOUBLE(d) 浮點數
RETURN_STRING(s, dup) RETVAL_STRING(s, dup) 字串。如果dup為1,引擎會呼叫estrdup()重複s,使用拷貝。如果dup為0,就使用s
RETURN_STRINGL(s, l, dup) RETVAL_STRINGL(s, l, dup) 長度為l的字串值。與上一個巨集一樣,但因為s的長度被指定,所以速度更快。
RETURN_TRUE RETVAL_TRUE 返回布林值true。注意到這個巨集沒有括號。
RETURN_FALSE RETVAL_FALSE 返回布林值false。注意到這個巨集沒有括號。
RETURN_RESOURCE(r) RETVAL_RESOURCE(r) 資源控制代碼。
關於函式型別等詳細設定參見:http://www.laruence.com/2009/04/28/719.html

若在第5步沒有生成def檔案,這裡需要自己新增PHP_FUNCTION(a)和PHP_FUNCTION(b)兩個函式程式碼,並修改PHP_FUNCTION裡的zend_parse_parameters函式,這個函式用來將從php中傳入的引數轉換成c語言的引數型別。

zend_parse_parameters()函式大部分的程式碼看起來幾乎都一樣。ZEND_NUM_ARGS()向Zend Engine提供關於接收到的引數數量,TSRMLS_CC被用來保證執行緒安全,最後函式會返回SUCCESS或者FAILURE。在普通情況下zend_parse_parameters()將會返回SUCCESS;如果一個呼叫指令碼傳遞的引數數量超過了函式定義的引數數量,或者傳遞的引數不能轉換成合適的資料型別,Zend將會自動的輸出一個錯誤資訊,然後函式會優雅地把控制權返回給呼叫指令碼。

在這個例子你使用“s”來指明這個函式引數可以被轉換成string資料型別,“l”則表示long型別,資料型別指定符和對應型別如下表:

型別指定符 對應的C型別 描述
l long 符號整數
d double 浮點數
s char *, int 二進位制字串,長度
b zend_bool 邏輯型(1或0)
r zval * 資源(檔案指標,資料庫連線等)
a zval * 聯合陣列
o zval * 任何型別的物件
O zval * 指定型別的物件。需要提供目標物件的類型別
z zval * 無任何操作的zval
此外,還需要在myfunc_functions[]中新增:
const zend_function_entry myfunc_functions[] = {
	PHP_FE(confirm_myfunc_compiled,	NULL)		/* For testing, remove later. */
	PHP_FE(a,	NULL)
	PHP_FE(b,	NULL)
	PHP_FE_END	/* Must be the last line in myfunc_functions[] */
};

還需要在php_myfunc.h中加入函式宣告:

PHP_MINIT_FUNCTION(myfunc);
PHP_MSHUTDOWN_FUNCTION(myfunc);
PHP_RINIT_FUNCTION(myfunc);
PHP_RSHUTDOWN_FUNCTION(myfunc);
PHP_MINFO_FUNCTION(myfunc);


PHP_FUNCTION(confirm_myfunc_compiled);	/* For testing, remove later. */
PHP_FUNCTION(a);
PHP_FUNCTION(b);



8、修改config.m4

修改myfunc/config.m4檔案,去掉下面兩項的dnl註釋:

PHP_ARG_WITH(myfunc, for myfunc support,
dnl Make sure that the comment is aligned:
[  --with-myfunc             Include myfunc support])

dnl Otherwise use enable:

PHP_ARG_ENABLE(myfunc, whether to enable myfunc support,
dnl Make sure that the comment is aligned:
[  --enable-myfunc           Enable myfunc support])


9、編譯並生成dll

(1)用VS2013開啟myfunc/myfunc.dsp

(2)在BUILD -> Configuration Manager中,將Active Solution Configuration設定成Release_TS

(3)編譯工程,BUILD->Build myfunc

(4)在C:\wamp\bin\php\php5.5.12\Release_TS下生成php_myfunc.dll


10、新增php5ts.lib

若編譯報錯缺少該檔案,將C:\wamp\bin\php\php5.5.12\dev目錄下的php5ts.lib檔案拷貝到C:\wamp\bin\php\php5.5.12\ext\myfunc目錄下

myfunc資料夾不能移出ext資料夾,否則編譯會報缺少php.h


11、新增config.w32.h

若編譯報錯缺少該檔案,在網上下載該檔案,或新建檔案拷貝如下程式碼:

#define SIZEOF_LONG 4
#define PHP_COMPILER_ID "VC11"

其中第二行是為了取消載入php_myfunc.dll時的編譯器檢查,這裡需要將其改為你安裝的VC編譯器的版本,如VS2013是VC11

將該檔案放在C:\wamp\bin\php\php5.5.12\main目錄下


12、整合dll到php中

(1)將生成的php_myfunc.dll放到php環境下的ext目錄下

(2)修改php.ini,新增extension=php_myfunc.dll,重啟apache

(3)在C:\wamp\bin\php\php5.5.12下新建test.php,內容為

<?php 
echo a(3,5)."\n"; 
echo b("string1","string2")."\n";
?>

在控制檯呼叫,得到結果:
[email protected] /cygdrive/c/wamp/bin/php/php5.5.12
$ php test.php
8
string1string2


參考:

http://wenku.baidu.com/link?url=ZtvcBS4oChuRqrn6LaABMZqhaHZOVBUq77UKE79WT50xeptaBxkHfKAnkrAgizVjGlRlzczxZypj749dZcDM61ogWEv0Z67MpCD9FvSWEv7

http://www.laruence.com/2009/04/28/719.html

http://blog.csdn.net/a600423444/article/details/8108993

http://blog.chinaunix.net/uid-25007056-id-3781616.html

http://www.3qphp.com/index/show/index/4.html

http://www.t086.com/article/4866

http://www.kissthink.com/archive/C-Programming-PHP-call-summary-windows.html

http://www.techotaku.net/2013/09/build-php-and-extension-for-windows/

相關推薦

WindowsC擴充套件PHP打包dll方法

1、目的 為了在php中使用C語言的擴充套件,本文介紹在windows系統下,將C擴充套件打包成dll檔案,提供給php呼叫的方法 Linux系統下的方法見:http://c.biancheng.net/cpp/html/1400.html 2、需要安裝的軟體 (1)wa

windowsC++獲取本機IP地址

ali 返回 轉換成 data info AC ctrl nag != BSTR CamUtilsCtrl::GET_TERM_IP(void){ AFX_MANAGE_STATE(AfxGetStaticModuleState()); CString strResult

C++擴充套件php時函式重定義redefinition問題

問題:我在用C++擴充套件php時,用到了一些數學庫函式如sqr,sqrt等,需要在C++擴充套件工程的原始檔test.cpp中#include <math.h>,但是編譯時發現這些函數出現了重定義redefinition的問題。 多次嘗試後,發現將test.c

Windowsc++來呼叫tensorflow訓練好的模型

     歷經千辛萬苦終於把這一關給過了,對一個菜鳥來說,終於算是鬆了一口氣。。。    首先我想說明的一下是常見的tensorflow訓練好的模型儲存方式有兩種:ckpt格式和pb格式,其中前者主要用於暫存我們訓練的臨時資料,避免發生意外導致訓練終止,前面的努力全部白費掉了

WindowsDirectShow查詢攝像頭含解析度和麥克風

        在視訊聊天、視訊會議、線上監控和視訊展臺等專案中,需要查找出本地電腦上連線的所有攝像頭,網上流傳比較多的方式是ffmpeg的方式,這種方式可以跨平臺,不同的平臺下呼叫不同的庫。這種方式在控制檯直接列印了攝像頭的資訊,無法(或者說我暫時沒找到)在記憶體中獲取,

ActiveMQ在Windows的安裝與啟動懶人專屬

最新 lin 管理 star 新的 tro 安裝目錄 min 1.5 其實這些ActiveMQ官網都有,但是如果你懶得看官網,那就直接看這吧! 1. 官網下載最新的ActiveMQ安裝包 apache-activemq-x.x.x-bin.zip並解壓 2.進入安

windows如何將Python文件打包.exe可執行文件

問題 help inux exe python文件 由於 工具 linux 編寫   在使用Python做開發的時候,時不時會給自己編寫了一些小工具輔助自己的工作,但是由於開發依賴環境問題,多數只能在自己電腦上運行,拿到其它電腦後就沒法運行了。這顯得很不方便,不符合我們

WindowsPython環境搭建圖解3.6.2

Windows下Python(pip)環境搭建(3.6)圖解 ----------------小白一隻,學習整理中。。。。轉載請標明,謝謝------------------------------------------- 1:下載最新的Python安裝:3.6.2

Windows Redis叢集的搭建 ——超詳細版

1、下載並安裝Redis 本人安裝到C盤了,在C:\Redis 下建立Logs資料夾 , 然後在C:\Redis 建立 3個不同的Redis例項    ①、 redis.6380.co

UEFI啟動的windows安裝Ubuntu雙系統親測可行

       不瞞你說,我和你一樣,曾經把ubuntu kylin14.04和win7/8/8.1安裝在一起,win7沒有問題,因為win7我用的是一臺比較老的電腦,不是UEFI啟動模式,但是我自己電腦上裝的正版win8/6.1是UEFI引導模式的,當我按照網上的教程裝好Ub

WindowsCodeblocks建立一個最簡單的DLL動態連結庫

建立一個最簡單的只有一個get_id() 函式的DLL庫  一、建立C語言動態連結庫 1.新建一個動態庫的工程 File - New - Project - DLL - Go 新建的工程原來的main.cpp和main.h刪除,新建兩個檔案simple.

Android逆向基礎筆記—Android NDK開發2之Windows的gcc手動編譯交叉連編譯和利Linux Ubuntu系統的交叉工具鏈手動編譯

一、交叉工具鏈 這些工具都在NDK的路徑下:E:\Android\android-ndk-r13\toolchains\arm-linux-androideabi-4.9\prebuilt\windo

windowscmd使用wget命令含安裝包

我們都知道wget這個工具是Linux、Unix下才能使用的。那麼windows平臺下到底可否使用?答案是確定的可以的!!!        請從下面連結下載wget(1.11.4) for win: 。下載完成後,解壓出wget.exe檔案,把它放到c:\windows

4如何給硬碟調整分割槽邏輯分割槽或拓展分割槽無法給主分割槽容量怎麼辦?windows如何更改碟符第九步?如何新建磁碟?第八步

使用DiskGenius工具進行調整分割槽。調整分割槽前先看下是否所有碟符(C盤、D盤等等)都是主分割槽。如果不是,則需要全部轉換成主分割槽,否則將不能自由調整。因為邏輯分割槽和主分割槽之間的容量無法相互拓展容量的。一般使用第三方的什麼刷機工具或者去電腦城刷機,都會把C盤給你

C#實現MVCModel View Control模式介紹

益處     在我們的開發專案中使用MVC(Model-View-Control)模式的益處是,可以完全降低業務層和應用表示層的相互影響。此外,我們會有完全獨立的物件來操作表示層。MVC在我們專案中提供的這種物件和層之間的獨立,將使我們的維護變得更簡單使我們的程式碼重用變得

WindowsPython你會幾種copy檔案的方法以及效率分析

001:os.system import os import tempfile filename1 = tempfile.mktemp (".txt") open (filename1, "w").close () filename2 = filename1 + ".co

windows使用cx_freeze將Python程式打包exe可執行檔案

1.cxfreeze安裝 https://pypi.python.org/pypi/cx_Freeze 在以上地址可下載最新版本,選擇適合自己python版本的安裝包。安裝過程中會自動識別你的pytho

WINDOWS的目錄對映工具微軟官方工具

Linux下使用mount做目錄對映很方便,Windows下也有類似的工具可以使用-----Junction  Windows 2000 以及更高版本都支援目錄符號連結,其中目錄作為到計算機上另一目錄的符號連結。例如,如果目錄 D:\SYMLINK 指定 C:\WIN

android元件化打包module遇到的問題總結打包aar

在一開始接觸APICLoud平臺的時候我是拒絕的,因為對於一個有著熟練的java技能,掌握著老舊設計模式的人來說,這種平臺簡直就是對於程式設計師這個職業的侮辱。第一個原因是APICLoud平臺剝離了原生開發和html+js開發的職責,使得原生開發的職業方向越來越

MFC 頁面打包DLL方法 _ 解決Max匯出外掛的windows.h 標頭檔案衝突

教程: https://jingyan.baidu.com/album/49711c619e0e20fa451b7c40.html