在Linux上建立PHP4的C++擴充

來源:互聯網
上載者:User

Jason
1. 必須的工具
2. 主要步驟

    2.1. 建立
    2.2. 編譯
    2.3. 調試

3. 總結

1. 必須的工具

如下工具是必須的:

   1.

      gcc. 我使用的是3.4.3
   2.

      autoconf. 我使用的是2.13-5. 奇怪的是2.59是不能用的,如果你的系統裡安裝的是這個版本,要先卸載,然後安裝2.13
   3.

      PHP4的原始碼。我使用的是PHP-4.4.4。在PHP的網站上可以下載到

2. 主要步驟

建立PHP的擴充很麻煩。熟悉其它指令碼語言的人會覺得開發PHP的擴充真是羅嗦到了極點。不過給指令碼寫擴充的原理都是一樣的:

匯出一個特定名字的函數,然後通過這個函數返回關於這個擴充的全部資訊,其中重要的有:

   1.

      名字,描述,版本資訊
   2.

      模組所提供的功能,這個一般都是一個函數名和函數指標成對的數組
   3.

      通過一些函數實現指令碼和擴充之間的資料交換.這方面各個語言都不相同,TCL是直接傳遞字串,Python提供了PyArg_ParseTuple,Py_BuildValue等函數,Lua則通過一個堆棧來交換資料.

PHP提供了一系列的工具和宏來封裝這個過程,可惜的是在我看來這反而讓它更加複雜。
2.1. 建立

   1.

      將PHP-4 的原始碼解壓縮。下文將這個目錄稱為PHPSRC.
   2.

      進入PHPSRC/ext目錄,執行./ext_skel副檔名。假設我們的副檔名字叫testext,那就是輸入./ext_skeltestext. 這個程式將會為你在ext目錄下建立如下內容:
         1.

            testext目錄
         2.

            在testext目錄下又包括:
               1.

                 testext.c - 這是擴充模組的源檔案
               2.

                 php_testext.h - 標頭檔
               3.

                 config.m4 - 用於autoconf的設定檔,autoconf會通過這個檔案的內容決定應該如何編譯連結這個模組。
               4.

                 testext.php - 自動產生的測試指令碼
               5.

                 tests 目錄 - 忽略
   3.

      然後我們必須簡單的理解一下config.m4這個檔案。

      m4 is a macro processor, in the sense that it copiesits input to the output, expanding macros as it goes. Macros are either builtinor user-defined, and can take any number of arguments. Besides just doing macroexpansion, m4 has builtin functions for including
named files, running shellcommands, doing integer arithmetic, manipulating text in various ways,performing recursion, etc.... m4 can be used either as a front-end to acompiler, or as a macro processor in its own right.

      The m4 macro processor is widely available on allUNIXes, and has been standardized by POSIX. Usually, only a small percentage ofusers are aware of its existence. However, those who find it often becomecommitted users. The popularity of GNU Autoconf, which
requires GNU m4 forgenerating configure scripts, is an incentive for many to install it, whilethese people will not themselves program in m4. GNU m4 is mostly compatiblewith the System V, Release 3 version, except for some minor differences. SeeCompatibility,
for more details.

      Some people find m4 to be fairly addictive. Theyfirst use m4 for simple problems, then take bigger and bigger challenges,learning how to write complex sets of m4 macros along the way. Once reallyaddicted, users pursue writing of sophisticated m4 applications
even to solvesimple problems, devoting more time debugging their m4 scripts than doing realwork. Beware that m4 may be dangerous for the health of compulsive programmers.

      以上內容來自http://www.gnu.org,所以我就不多說了. 總之PHP使用了這種技術來協助我們構建擴充.

      只記錄一下對我們有用的東西:
         1.

            dnl是注釋.好怪
         2.

            PHP_ARG_WITH或者PHP_ARG_ENABLE指定了PHP模組的工作方式,任選一種,我選擇的是WITH
         3.

            PHP_REQUIRE_CXX()用於指定這個擴充用到了C++
         4.

            PHP_SUBST(SYSFILE_SHARED_LIBADD)用於說明這個擴充編譯成動態連結程式庫的形式(SYSFILE=ModuleName,漏了這句也不行,在測試的時候,可知道,這句使Makefile中多了一行:SYSFILE_SHARED_LIBADD=-l stdc++,沒有這句編譯雖然通過,但是在php載入**.so檔案的時候,找不到擴充函數)
         5.

            PHP_ADD_LIBRARY(stdc++,"",SYSFILE_SHARED_LIBADD)用於將標準C++庫連結進入擴充
         6.

            PHP_NEW_EXTENSION用於指定有哪些源檔案應該被編譯,檔案和檔案之間用空格隔開.

      ext_skel預設產生的模組架構是針對C的,我們要使用C++,那以上的3,4,5,三個個宏就是必須的.另外還要把testext.c改名成testext.cpp,所以

PHP_NEW_EXTENSION原本包括的testext.c也要修改.

      在使用C++之後要注意一個小問題,那就是php_testext.h這個檔案可能被PHP的其他部分所引用到,而引用者很可能是一個.c檔案,所以不能在php_testext.h裡包含任何C++所專屬的東西.比如標準模版庫,類,或者bool類型等等.
   4.

      預設產生的testext.c(現在改名為testext.cpp)了,已經包含了一個測試性質的匯出函數,通過那個例子就可以大概明白怎麼添加自己的函數了. zend_function_entry是匯出函數列表,zend_module_entry描述了模組的資訊. 不過因為是C++了,還是有幾點要修改的:
         1.

            #include "php.h"#include "php_ini.h" #include "ext/standard/info.h"

            要用extern "C" 修飾.
         2.

            ZEND_GET_MODULE也要用extern "C"修飾
         3.

            zend_module_entry就是用於描述模組資訊的類型,其實就是一個結構,其中第二項不知道是什麼含意.在Windows上,這好像是一個描述資訊,可以是一個長長的字串,但是在Linux上似乎只能是跟模組名相同.
   5.

      之後的工作就是寫自己的代碼了.根據設計,提供對外的介面函數,然後寫C/C++代碼來實現.

2.2. 編譯

   1.

      代碼寫好以後,到PHPSRC目錄,運行./buildconf --force,除非m4檔案有錯或者autoconf安裝有問題,否則這個步驟不會有什麼錯誤,時間也不長. 通過刪除configure檔案,可以強迫buildconf重建一遍.
   2.

      運行./configure --disable-all--with-testext=shared

      --disable-all是為了減少配置和下一步編譯的時間,因為我們只需要自己的模組

      --with-testext=shared指明了講這個模組編譯成動態連結程式庫,而不是整合到PHP內部
   3.

      運行make

      這個過程時間比較長,如果你的代碼有問題,就會出現編譯或者連結錯誤,根據提示自己修改就是了. 如果沒什麼問題,就會在PHPSRC/modules下面產生擴充檔案testext.so,同時也會產生PHPSRC/sapi/cli/php. 可以運行./sapi/cli/appext/testext/testext.php來測試模組是否正常. 不過這之前要先把testext.so複製到某個特定的目錄下,這個目錄不同的系統不一樣,你可以根據運行/sapi/cli/appext/testext/testext.php得到的錯誤資訊來知道這個目錄.
   4.

      如果測試沒有問題,就可以安裝到正式的PHP裡去了,通過修改php.ini檔案然後重起Apache就可以.

2.3. 調試

用gdb可以調試PHP的擴充.首先要寫一個php指令碼用來測試你想測試的功能, 把它放到PHPSRC目錄下,比如叫test.php. 然後按如下步驟進行:

   1.

      gdb
   2.

      file ./sapi/cli/php
   3.

      用b命令下斷點.因為是C++程式,所以擴充的匯出函數名並不是我們輸入的名字,可以用nm命令查看擴充的所有匯出函數,找到編譯器最終分配的名字.這個名字是肯定包含了你原本輸入的名字的,所以很好找.

      gdb會提示說這個符號在當前程式(php)裡找不到,問你要不要在以後的shared library裡找,回答Yes
   4.

      run test.php,之後就會停在斷點上了.用n,s,display之類的命令調試的.

3. 總結

一句話,PHP的模組擴充比誰都麻煩,規則太多.其實我希望它提供一個文檔,提供我在第二節開頭描述的那些資訊就夠了. 不過也許是我學藝不精吧,對本來挺正常的事深惡痛絕

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.