Реализация классов в PHP5 экстеншене, часть 3

Ирокез

бессмертный пони
Команда форума
Партнер клуба
Реализация классов в PHP5 экстеншене, часть 3

Вот и подошла наверно очередь и третьей заключительной части по реализации классов в экстеншенах. В ней будет рассмотрен вопрос о связывании указателя this с произвольной С структурой, "перегрузкой" метода создания объекта класса и вкратце ряда предопределённых методов (__call, __set, __get, __clone).

На практике, при разработке класса в экстеншене, не всегда удобно хранить значения переменных в zval- структурах. Для связывания неявного указателя this и произвольной С структуры предусмотрен специальный механизм, называемый 'objects storage', но воспользоваться можно им имея указатель на экземпляр класса.

Начнём по порядку, прежде чем связать объект со структурой, давайте перегрузим метод, отвечающий за создание экземпляра класса, а именно "new". Для этого вернёмся к определённой нами функции PHP_MINIT_FUNCTION(cfoo) и добавим в неё всего лишь одну строчку:
PHP:
PHP_MINIT_FUNCTION(cfoo)
{
	zend_class_entry	stubClassEntry;

	INIT_CLASS_ENTRY(stubClassEntry,"CFoo",class_methods);

	/* Собственно это и есть перегрузка функции отвечающей за создание объекта */	
	stubClassEntry.create_object = CFoo_New;

	g_ClassEntry = zend_register_internal_class(&stubClassEntry TSRMLS_CC);

	zend_declare_property_string(g_ClassEntry,"var",3,"Hello CFoo",ZEND_ACC_PRIVATE TSRMLS_CC);
	zend_declare_property_long(g_ClassEntry,"long_var",8,54321,ZEND_ACC_PUBLIC TSRMLS_CC);
	zend_declare_property_long(g_ClassEntry,"static_var",10,5,ZEND_ACC_PUBLIC|ZEND_ACC_STATIC TSRMLS_CC);

	return SUCCESS;
}
Теперь нам необходимо определить саму функцию CFoo_New, дабы контролировать процесс :).

PHP:
zend_object_value CFoo_New(zend_class_entry *class_type TSRMLS_DC)
{
	CFoo_Extra		*intern;
	zend_object_value	retval;
	zval			tmp;

	intern = emalloc(sizeof(CFoo_Extra));

	zend_object_std_init(&intern->сlassInstance, class_type TSRMLS_CC);
	zend_hash_copy(intern->сlassInstance.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
	intern->classExtraInt = 45;
	intern->classExtraStr = "CFoo Extra C structure";

	retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) CFoo_Delete, NULL TSRMLS_CC);
	retval.handlers = &((g_ClassHandlers));

	return retval;
}
Рассмотрим, произошедшее в деталях. CFoo_Extra - как не трудно догадаться, это и есть наша произвольная C структура, произвольная она в некотором смысле, потому как в ней должна быть обязательная предопределённая информация:

PHP:
typedef struct _CFoo_Extra {
	zend_object		сlassInstance;	// Именно это она и есть.
	int			classExtraInt;
	char*			classExtraStr;
} CFoo_Extra;
распределяем место, под нашу структуру, инициализируем объект класса в нашей структуре zend_object_std_init, копируем свойства zend_hash_copy, тут вроде как все понятно. Далее инициализируем саму структуру. Вот после этого самое интересное, запихиваем наш объектик в "objects storage". zend_objects_store_put, первый параметр, указатель на нашу структуру, второй, указатель на деструктор объекта класса, а вот третий параметр, деструктор нашего объектика CFoo_Delete ( мы же не хотим иметь в своем экстеншене memory leakes )
PHP:
void CFoo_Delete(void *object TSRMLS_DC)
{
	CFoo_Extra *intern = (CFoo_Extra *)object;
	
	intern->classExtraInt = 0;
	intern->classExtraStr = NULL;

	zend_object_std_dtor(&intern->classInstance TSRMLS_CC);
	efree(object);
}
После того, как добавили все для работы с нашими экстра данными класса, наверно необходимо как-то получать к ним доступ из наших методов, все что нам для этого надо, как говорилось выше, иметь лишь указатель на объект (this).
PHP:
CFoo_Extra*	ExThis = (CFoo_Extra*)zend_object_store_get_object(getThis() TSRMLS_CC);
Вот собственно и все :).

Как всегда, исходники того что было сделано.

foo 2008.03.21 10.01.rar 8Кб

Практически аналогично, перегружаются все предопределённые методы, и наверно нет необходимости копи-пастить их здесь :)

Спасибо, всем кто читал, кому это было интересно. Я не претендую и 100% корректность терминов и надеюсь что хоть кому-то, мои исследования помогут в создании своих суппер-экстнешенов. Ещё раз спасибо за внимание.
 

korchasa

LIMB infected
Спасибо за статьи. Я уверен, что помогут.

ЗЫ: Только еще бы нулевую, про азы работы с расширениями. Почему то не смог в свое время найти такой информации, и пришлось "сквозь грабли, к звездам".
 

fixxxer

К.О.
Партнер клуба
>> Только еще бы нулевую, про азы работы с расширениями

Extending and Embedding PHP
By Sara Golemon
...............................................
Publisher: Sams
Pub Date: May 30, 2006
Print ISBN-10: 0-672-32704-X
Print ISBN-13: 978-0-672-32704-9
Pages: 456

нелегальный chm легко найти в гугле ;)
 

korchasa

LIMB infected
Спасибо за ссылки. В итоге и пришел к мануалу. Просто в начале мысль искать там, даже не возникла - видимо уже избалован туториалами how-to-do-something.

ЗЫ: Книгу закажу
 

Alexandre

PHPПенсионер
Только еще бы нулевую, про азы работы с расширениями. Почему то не смог в свое время найти такой информации, и пришлось "сквозь грабли, к звездам".
в офф мане есть и на zend.com
Ирокез спасибо - очень полезно, только бы хорошо это все выложить в статьях, в форуме это все потеряется, или скомплектуй материал и вышли nw, он напечатает в PHPInside.

PS - что-то я предыдущие две части упустил, буду искать :)
 

Alexandre

PHPПенсионер
они где-то рядом
да прочел сразу же после этой. Статью однозначно надо в детали и в PHPInside.

-~{}~ 21.03.08 20:42:

Extending and Embedding PHP
By Sara Golemon
да, хорошая книга для стартапа,
кстати можно на офф сайтах пхп и пхп-конф найти презентации выступлений Сары по пхп-ext
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
Спасибо, за интерес к статьям. Если бы, можно было картинки подсовывать (может и можно, но я не знаю как), выложил бы подробный мануал как настраивать проекты что-бы компилировалось в IDE VS и KDevelop, ну и так всякого по мелочам, вызовы функций из экстеншена, доступ к свойствам класса и т.д.

Alexandre
Если статья полезная, то наверно и надо выложить, людям в помощь, но я не знаю ни формат статей, ни тем более нужность ее для PHPInside, а напрашиваться .... ;)
 

fixxxer

К.О.
Партнер клуба
обращаться никуда не надо, там открытая регистрация :)
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
Тогда если, можно, замечания по статьям, что убрать, что добавить, во что углубиться, и с молчаливого согласия fixxxer:) , обязательно выложу.
 

korchasa

LIMB infected
Автор оригинала: Ирокез
Тогда если, можно, замечания по статьям, что убрать, что добавить, во что углубиться...
Тесты ;)
Ну и введение, если не сложно. Будет законченный цикл.
 

Santiago

Новичок
korchasa
Статьи Сары на devzone:
http://devzone.zend.com/author/4580-SaraMG

Если по-русски, то книги "Профессиональное программирование" Джорджа Шлосснейгла и "PHP5 профессиональное программирование" Энди Гутманса. Там есть отдельные разделы, посвященные расширениям.
 

atv

Новичок
Статьи очень нужные. Спасибо. Ещё хочется узнать мнение автора о возможности автоматической генерации C кода по коду PHP класса. Насколько это реально. А может есть уже готовые проекты?
 

tony2001

TeaM PHPClub
разделы, книжки и статьи могут помочь, если вы собираетесь этим заниматься _в теории_.
реальную задачу надо садиться и решать, благо примеров экстеншенов масса, выбирайте наиболее похожий и смотрите как там сделано.

atv
см. http://pear.php.net/package/CodeGen_PECL
голову и руки, правда, ни один автогенератор не сможет заменить.
 

atv

Новичок
голову и руки, правда, ни один автогенератор не сможет заменить.
Чай не вчера родился, понимаю :) Зато автогенератор может в разы упростить задачу синхронизации проекта, поддерживаемого и на PHP и на C.
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
atv
в принципе tony2001 прав, но наверно Вы имели ввиду не просто генерацию экстеншена с классом, а перевод PHP кода в C код (for, if, switch и т.д.). Задача интересная и наверно реализуемая, но думаю что PHP создавался не для того, чтобы его переводили в С (хотя в некоторых случаях, без этого не обойтись, но лишь в некоторых).
Имхо, бездумный автоматический перевод кода, в любом случае не решит проблем надёжности, быстроты и функциональности, практически любой экстеншен требует своего подхода и не факт что автоматически переведённый php код будет выполнять то, что задумал автор.

PS: Признаюсь, несколько человек уже обращались ко мне с подобными вопросами.
 

atv

Новичок
Имхо, бездумный автоматический перевод кода, в любом случае не решит проблем надёжности, быстроты и функциональности
Собственно об этом и был вопрос. Так как сам не имею практического опыта портирования проекта с PHP на С расширение, было интересно узнать, возможно ли это автоматизировать.
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
atv
В принципе не сложный скрипт, вполне возможно портировать, но боюсь что скорее всего, это будет линейный код, хотя если копать глубже, то вполне можно сделать 60-80% автопереноса ( :) )
 
Сверху