Я новичок в этой области написания расширений для PHP, однако мне нужно создать класс-оболочку для C ++ для PHP. В настоящее время я использую PHP 5.2.13. Я прочитал эту статью http://devzone.zend.com/article/4486-Wrapping-C-Classes-in-a-PHP-Extension , учебник о том, как я могу перейти к тому, чтобы связать класс C ++ с PHP Zend, но это записывается в систему linux. У вас, ребята, есть какая-либо статья или совет о том, как я могу начать писать класс-оболочку для связи с PHP?
Это именно то, что я делал в последнее время. Учебник, на который вы ссылались, является хорошим (это была и моя отправная точка). Вот основной процесс, который я выполнил для упаковки моих классов. Предположим, вы завершаете свой класс C ++ с именем Myclass
:
Создайте php_myclass.h :
#ifndef PHP_MYCLASS_H #define PHP_MYCLASS_H extern "C" { #include "php.h" } // Включить определение класса C ++ #include "Myclass.h" // Вот структура, которая будет представлять PHP-версию вашего Myclass. // Он просто включает в себя указатель на Myclass и zend_object для PHP для struct myclass_object { zend_object std; Myclass * myclass; }; // Вот что ваш PHP-класс будет вызываться в пользовательском пространстве (PHP-код) #define PHP_MYCLASS_CLASSNAME "Myclass" extern zend_class_entry * myclass_ce; extern zend_object_handlers myclass_object_handlers; zend_object_value myclass_create_handler (zend_class_entry * type TSRMLS_DC); // Позже это будет массив, полный ваших объявлений метода Myclass. extern function_entry php_myclass_functions []; #endif / * PHP_MYCLASS_H * /
Затем определите свой php-класс в php_myclass.cpp :
#include "php_myclass.h" zend_class_entry * myclass_ce; zend_object_handlers myclass_object_handlers; // Я все еще новичок, но я думаю, что это функция, которая обрабатывает управление памятью, когда // класс PHP удаляется (выходит за рамки, заканчивается скрипт, что угодно) void myclass_free_storage (объект void * TSRMLS_DC) { объект myclass_object * obj = (myclass_object *); удалить obj-> myclass; zend_hash_destroy (obj-> std.properties); FREE_HASHTABLE (obj-> std.properties); efree (OBJ); } // И точно так же я считаю, что это ручка, как следует из названия, управление mem // когда создается экземпляр Myclass. zend_object_value myclass_create_handler (zend_class_entry * type TSRMLS_DC) { zval * tmp; zend_object_value retval; // создаем место в памяти для нового объекта Myclass PHP: myclass_object * obj = (myclass_object *) emalloc (sizeof (myclass_object)); // Заполните эту память с помощью 0s memset (obj, 0, sizeof (myclass_object)); obj-> std.ce = type; // какой-то волшебный материал (не знаю) ALLOC_HASHTABLE (obj-> std.properties); zend_hash_init (obj-> std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy (obj-> std.properties, & type-> default_properties, (copy_ctor_func_t) zval_add_ref, (void *) & tmp, sizeof (zval *)); // сделаем так, чтобы вы могли получить экземпляр этого объекта в более позднем коде retval.handle = zend_objects_store_put (obj, NULL, myclass_free_storage, NULL TSRMLS_CC); retval.handlers = & myclass_object_handlers; return retval; } // Сначала мы определяем некоторую информацию о аргументе для методов, которые принимают аргументы (если они есть) // Это означает, очевидно, один аргумент: ZEND_BEGIN_ARG_INFO_EX (php_myclass_one_arg, 0, 0, 1) ZEND_END_ARG_INFO () // Это два аргумента и т. Д. ZEND_BEGIN_ARG_INFO_EX (php_myclass_two_args, 0, 0, 2) ZEND_END_ARG_INFO () // Здесь вы указываете PHP, какие методы имеют класс Myclass PHP. function_entry php_myclass_functions [] = { // Специальное свойство в конце этой строки для конструктора: PHP_ME (Myclass, __ конструкт, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR) // Нормальные методы выглядят так: PHP_ME (Myclass, methodNameNoArgs, NULL, ZEND_ACC_PUBLIC) PHP_ME (Myclass, methodName1Arg, php_myclass_one_arg, ZEND_ACC_PUBLIC) PHP_ME (Myclass, methodName2Args, php_myclass_two_args, ZEND_ACC_PUBLIC) // Три волшебных значения NULL, не знаю, зачем им здесь идти. {NULL, NULL, NULL} }; // И теперь, определите каждый из тех методов Myclass, которым вы просто написали PHP // для отображения в пользовательском пространстве: PHP_METHOD (Myclass, __construct) { Myclass * myclass = NULL; zval * object = getThis (); // Создаем экземпляр класса, который вы обертываете myclass = new Myclass (); // Сделать объект (который указывает на $ this для вашего экземпляра объекта PHP) // экземпляр структуры, представляющей ваш php-класс myclass_object * obj = (myclass_object *) zend_object_store_get_object (объект TSRMLS_CC); // Установите внутренний класс Myclass этого экземпляра Myclass, который вы только что создали obj-> myclass = myclass; // Готово. } PHP_METHOD (Myclass, methodNameNoArgs) { // Получаем текущий экземпляр вашего класса Myclass в myclass: Myclass * myclass; myclass_object * mo = (myclass_object *) zend_object_store_get_object (getThis () TSRMLS_CC); \ myclass = mo-> myclass; if (obj == NULL) { // проверка ошибок RETURN_NULL (); } // Возвращаем значение вашего метода myclass с использованием одного из макросов RETURN_ * // Здесь мы притворимся, что это возвращает boolean: RETURN_BOOL (myclass-> methodNameNoArgs ()); } PHP_METHOD (Myclass, methodName1Arg) { // Теперь давайте притворимся, что Myclass :: methodName1Arg (int) принимает int // и возвращает std :: vector (который вы хотите быть массивом) длинный параметр; // Получаем текущий экземпляр вашего класса Myclass в myclass: Myclass * myclass; myclass_object * mo = (myclass_object *) zend_object_store_get_object (getThis () TSRMLS_CC); \ myclass = mo-> myclass; if (obj == NULL) { // проверка ошибок RETURN_NULL (); } // Вот как вы анализируете параметры вызова метода PHP. // Второй параметр - «l» для long int. Прочтите учебники онлайн для получения более подробной информации. // о том, как использовать эту функцию. if (zend_parse_parameters (ZEND_NUM_ARGS () TSRMLS_CC, "l", & param) == FAILURE) { RETURN_NULL (); } // Получить реальное возвращаемое значение, которое вы хотите перевести для PHP std :: vector retval = myclass-> methodName1Arg (param); // Используйте магическую «return_value» (которая находится в каждом методе за кадром) // и инициализировать его как массив PHP: array_init (return_value); // Прокручиваем вектор и строим массив: for (std :: vector :: iterator i = retval.begin (); i! = retval.end (); ++ i) { add_next_index_long (return_value, * i); } // сделанный. return_value всегда возвращается для вас. } PHP_METHOD (Myclass, methodName2Args) { // «В качестве упражнения для читателя» используется кодер-сленг для // «Я * действительно * не хочу больше набирать текст». :) }
Надеюсь, что этот примерный код компилируется или, по крайней мере, помогает. 🙂 Это было как-то поспешно составлено из настоящего рабочего кода, который у меня есть, и если поиск / замена сломают что-то, по крайней мере, вы можете получить представление о том, что делать. В этом много чего осталось, прочитайте учебник по расширению трех частей Sara Golemon по http://devzone.zend.com/article/1021 для получения дополнительной информации. Удачи.
Лучшая «документация», которую вы найдете, является исходным кодом PHP и является расширением (извините). Вы обнаружите, что вам нужно копаться в источниках (особенно в заголовках движка Zend), как только вы делаете что-то нетривиальное.
Сказав это, есть несколько ресурсов, которые могут оказаться полезными для начала работы. См. Эти статьи, а также расширение и внедрение PHP Sara Golemon . См. Также pecl.php.net/support.php