Пишем своё расширение PHP на C. Часть 2: Windows
В предыдущей статье я рассказывал как скомпилировать свое расширение PHP под Linux. Теперь разберемся, ка сделать это же под Windows.
Исходные данные
• Исходные коды расширения.
php_hello.c
php_hello.h
config.m4
config.w32
• Исходные коды php интерпретатора в установлены каталоге (ссылка: http://www.php.net/get/php-5.2.11.tar.bz2/from/a/mirror ): C:\php5_source
• Откомпилированная сборка php интерпретатора установлена в каталоге (ссылка: http://www.php.net/get/php-5.2.11-Win32.zip/from/a/mirror ): C:\php5
Среда Visual Studio C++ 6.0 выбрана исходя из того что все остальные расширения находящиеся в папке ext исходных кодов php интерпретатора собраны с ее помощью.
Несколько первых строк из файла проекта расширения gd.
1 2 3 4 5 6 7 8 9 |
# Microsoft Developer Studio Project File - Name="gd" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 CFG=gd - Win32 Release_TS GD2 !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run |
Необходимо создать новый проект Win32 dynamic dll.
Меню File->New
Рис.1
Выбираем тип проекта Win32 Dynamic-Link Library.
Рис.2
Сохранить проект в папку с остальными php расширениями. В каталог проекта скопировать файлы php_hello.c php_hello.h config.m4 config.w32. Результат на картинках далее.
Рис.3
Рис.4
Затем следует настроить проект.
Установить активную конфигурацию сборки. Set active configuration.
Рис.5
Активной конфигурацией должен быть Win32 – Release.
Рис.6
В свойствах проекта (Alt-F7) для конфигурации release .
Далее настройки компиляции. Category General.
Рис.7
Preprocessor definitions.
WIN32,_DEBUG,_WINDOWS,_MBCS,_USRDLL,PHP_HELLO_EXPORTS,ZEND_DEBUG=0,COMPILE_DL_HELLO,ZTS=1,ZEND_WIN32,PHP_WIN32
Должно получиться примерно так. Однако их могут быть и какие дополнительные еще препроцессорные определения.
COMPILE_DL_HELLO – выделена желтым часть имя нашего модуля. Допустим для модуля NEWMODULE будет так COMPILE_DL_NEWMODULE.
Настройки компиляции. Code generation.
Рис. 8
Use run-time library. Выбрать Multithreaded DLL.
Также настройки компиляции. Category preprocessor.
Рис.9
Additional include directories. ..\..,..\..\main,..\..\Zend,..\..\TSRM,..\..\bindlib_w32
Устанавливаем дополнительные каталоги для поиска *.h файлов относительно каталога с проектом.
Создать каталог C:\php_source\dev . Скопировать библиотеку php5ts.lib из откомпилированной сборки php интерпретатора (C:\php5\dev) той же версии в каталог C:\php_source\dev.
Настройки линковки.
Рис.10
Добавить в Object/Library modules ссылку на библиотеку php5ts.lib
Добавить в Additional library path путь к дополнительному каталогу для поиска lib файлов.
Добавить файлы с исходными кодами к проекту предварительно скопировав их в папку проекта.
Рис.11
Выбрать тип файлов: *.*
Можно выбрать и добавить сразу все файлы нажимая Ctrl.
Нажимаем ОК.
Рис.12
сonfig.m4 необязателен. Он нужен для сборки расширения под Unix.
Откомпилировать проект.
Рис.13
Скопировать полученную dll в рабочий каталог интерпретатора с расширениями php.
Рис.14
Исходники
test.php
1 2 3 4 5 6 7 8 9 10 11 12 |
<? dl("php_hello.dll"); $r="test string"; print($r); for($i; $i<100; $i++) { $t=hello_world(); print("$t\n\r"); } ?> |
php_hello.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "php_hello.h" static function_entry hello_functions[] = { PHP_FE(hello_world, NULL) {NULL, NULL, NULL} }; zend_module_entry hello_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_HELLO_WORLD_EXTNAME, hello_functions, NULL, NULL, NULL, NULL, NULL, #if ZEND_MODULE_API_NO >= 20010901 PHP_HELLO_WORLD_VERSION, #endif STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_HELLO ZEND_GET_MODULE(hello) #endif /* PHP functions here */ PHP_FUNCTION(hello_world) { RETURN_STRING("Hello World", 1); } |
php_hello.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#ifndef PHP_HELLO_H #define PHP_HELLO_H 1 #define PHP_HELLO_WORLD_VERSION "1.0" #define PHP_HELLO_WORLD_EXTNAME "hello" /* PHP function headers here */ PHP_FUNCTION(hello_world); extern zend_module_entry hello_module_entry; #define phpext_hello_ptr &hello_module_entry #endif |
config.w32
1 2 3 4 5 6 |
ARG_ENABLE("HELLO", "Hello module", "yes"); if (PHP_HELLO == "yes") { EXTENSION("php_hello", "php_hello.c"); AC_DEFINE('HAVE_HELLO', 1, 'Have pph hello'); } |
Так и не понял, зачем config.w32?
Она нужна для phpize, а здесь phpize никак не используется..