Обертка расширения PHP для C ++

Я новичок в этой области написания расширений для 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?

Solutions Collecting From Web of "Обертка расширения PHP для C ++"

Это именно то, что я делал в последнее время. Учебник, на который вы ссылались, является хорошим (это была и моя отправная точка). Вот основной процесс, который я выполнил для упаковки моих классов. Предположим, вы завершаете свой класс 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