Saját bővítmény készítése PHP-hoz

Előfordulhat, hogy olyan funkciót kell megvalósítanunk PHP-ban, amihez nem találunk a létező
kiterjesztések közt megfelelőt, ilyenkor (estleg) magunknak kell elkészítenünk. A cikkben szereplő példát Visual C++ Express-ben készítettem, kizárólag a saját szórakoztatásomra 🙂

Készítsünk egy új Win32 projektet, a varázsló második fülén az Application menüpontban választjuk ki a DLL-t, hiszen egy Win32-es DLL-t szeretnénk klszíteni, mert az összes PHP kiterjesztés Windows alatt DLL. Ha kiválasztottuk, akkor kapunk egy üres Visual C++ projektet, melyet már lefordíthatunk a Build menüpontból (értelme nincs, hiszen semmit nem csináltunk még).

Ezek után menjünk bele az Project Properties menübe és állítsuk be a projektünk sajátosságait:

1. a “Character Set” opciót állítsuk be “Use Multi-Byte Character Set”-re

2. a C/C++ -> Code Generation menüben állítsuk be ezeket:
1. Enable String Pooling = “Yes (/GF)”
2. Enable Minimal Rebuild = “No”
3. Basic Runtime Checks to =”Default”
4. Runtime Library = “Multi-threaded Debug (/MTd)”

3. a Configuration Properties > C/C++ > General fülön állítsuk be ezeket:
1. Debug Information Format = “Program Database (/Zi)”
2. Detect 64-bit Portability Issues = “No”

Ha ezeket beállítottuk akkor még be kell konfigurálnunk a PHP forráskódjából a megfelelő include elérési utakat, mert nélkülük nem fogjuk tudni lefordítani a ZEND engine-re épülő, friss és ropogós PHP kiterjesztésünket. Tehát menjünk a Configuration Properties -> C/C++ -> General fülön az “Additional Include Directories” menübe és itt adjuk hozzá a következő elérési utakat a projektünkhöz:

C:\PHPFORRAS\main
C:\PHPFORRAS\Zend
C:\PHPFORRAS\TSRM
C:\PHPFORRAS\

Ezek után az stdafx.h header fájlunk tartalmát írjuk át erre:

#pragma once
#include “zend_config.w32.h” //ZEND konfig
#include “php.h”

A “C:\PHPFORRAS” az a könyvtár ahová letöltöttük és kicsomagoltuk a PHP forráskódját.

A következő lépésben a Configuration Properties -> C/C++ -> Preprocessor fülön adjuk hozzá a következő változókat a projektunkhoz (ezeket a változókat a fordításnál használhatjuk):

ZEND_DEBUG=0
ZTS=1
ZEND_WIN32
PHP_WIN32

Ami még fontos az a Configuration Properties -> Linker -> Input fül beállítása, aholis a php5ts.lib fájl elérési útját kell megadnunk. Vigyázat! Ez nem a PHP forráskódjában található, hanem a lefordított PHP-ban ami nálam az XAMPP csomagban volt, így nálam ennek az elérési útja így nézett ki: C:\jani\xampp\xampp\php\dev\lib

Ha elkészültünk, akkor már le kell(ene) tudnunk fordítani a kiterjesztésünket. 🙂

Arra ügyeljünk, hogy a PHP és ZEND API – melyet használunk a fejlesztéshez, ugyanolyan verziójú legyen mint amivel a webszerverünk alatt futó PHP lett fordítva, gondolom ez evidens :), de azért szólok. Nem mellékes az sem, hogy a C++ fordító verziójának is egyeznie kell, aki XAMPP-ot használ az ne fordítsa a bővítményét Visual Studio 2008-al, mert az XAMPP VC6-al lett lefordítva.

Az 5.3.1-es PHP-nál a fejlesztők viccesek voltak… Ha ilyen verziójú PHP API-ból fordítasz, akkor a compiler keresni fogja a

c:\jani\phpsrc\php-5.3.1\tsrm\tsrm_config.w32.h
C:\jani\phpsrc\php-5.3.1\Zend\zend_config.w32.h

fájlokban a ../main/config.w32.h fájlt, ami természetesen nem létezik (miért is lenne jó helyen egy header fájl???) sem ezen az útvonalon sem másikon, helyette a PHPSRC\win32\build könyvtárban lesz egy config.w32.h.in nevű fájl, nah ezt át kell nevezni config.w32.h-ra és a projektünk beállításainál a Configuration Properties -> C/C++ -> General fülön az “Additional Include Directories” menüben az elérési utakhoz hozzá kell adni ezt a könyvtárat… A PHP 5.2-es verzióinál nincs ez a kellemetlenség.

Az én HelloWorld bővítményem forráskódja:

#include “stdafx.h”

/*
* ide kerülnek azok a függvények amelyeket a PHP bővítményünk tartalmazni fog
*/
ZEND_FUNCTION(HelloWorld);

zend_function_entry HelloWorldExtModule_functions[] = {
ZEND_FE(HelloWorld, NULL)
{NULL, NULL, NULL}
};

/* A bővítményünkről minden fontos információ */
zend_module_entry HelloWorldExtModule_module_entry = {
STANDARD_MODULE_HEADER,
“HelloWorldExt Module”,
HelloWorldExtModule_functions,
NULL, NULL, NULL, NULL, NULL,
NO_VERSION_YET, STANDARD_MODULE_PROPERTIES
};

ZEND_GET_MODULE(HelloWorldExtModule)

/* A HelloWorld függvény törzse – uhh, nem tul szep :)*/
ZEND_FUNCTION(HelloWorld){
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, “l”, &”Hello world!”) == FAILURE) {
RETURN_STRING(“Hibás paraméter!”, true);
}
RETURN_STRING(“Hello world!”,true);
}

Ha nem szeretnéd mindezt egyesével beállítgatni, akkor használhatod azt a sablon projektet, amit készítettem neked, erről a címről letöltheted:

http://sites.google.com/site/vajdajanos/ddd/HelloWorldExt.zip?attredirects=0&d=1

Ha letöltöd a ZIP fájlt, akkor ne felejtsd el átírni a projekt konfigjában az elérési utakat a Te PHP forráskódod elérési útjai alapján!

Ha ezzel megvagy, akkor tudsz fordítani (build) és máris tesztelheted a bővítményedet. 🙂

A php.ini-ben még engedélyezni kell:
extension=php_helloworld_ext.dll

És a PHP teszt:

HelloWorld(1); //paramétert csak viccből kapott, hogy lássuk a hibakezelést is
This entry was posted in php, php extension, visual C++. Bookmark the permalink.

2 Responses to Saját bővítmény készítése PHP-hoz

  1. margó says:

    szia!ez nagyon érdekes, még soha nem csináltam saját extensiont, de ez alapján sikerült összehoznom 🙂 nem tudom mire lesz jó, de pl. cachelésre tudám használni, vagy intranetes rendszerekben….köszi!

  2. j. says:

    szia,köszi, szerintem is sok dologra használható, mindenképpen érdemes használni ezt a lehetőséget nagyobb fejlesztéseknél.

Leave a comment