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