ФорумПрограммированиеPHP для идиотовРасширения PHP → Написание расширения для php на c

Написание расширения для php на c

  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 27 февраля 2012 г. 14:09

    Приветствую всех.

    Возникла надобность написать расширение для php.

    Минимальная задача - реализовать вот такой класс:


    class MyClass {
    protected $attrs = array();
    public function __construct() {
    $this->attrs['id'] = '';
    $this->attrs['name'] = '';
    }
    public function __get($key) {
    if (array_key_exists($key, $this->attr))
    return $this->attrs[$key];
    }
    public function __set($key, $value) {
    if (array_key_exists($key, $this->attr))
    $this->attrs[$key] = $value;
    }
    }


    На данный момент, по тем манам что удалось нарыть в сети с большим трудом, имеется:
    Описание класса с нужным свойством и конструктор.

    Т.е. я уже могу подключить своё расширение, написать

    $c = new MyClass();
    var_dump($c);

    и увидеть что экземпляр есть и он содержит то что ожидается.

    Теперь, когда надо реализовать __get __set - немного застпорился.
    Во-первых, не силён в сях. Не знаю, следует ли мне хранить свойства в отдельной своей структуре,
    или каждый раз обращаться за zend_read_property/zend_update_property?

    Мне нужен пример реализации такого __get как в примере.
    Есть ли здесь достаточные специалисты чтобы помочь?

    Сишный код при необходимости покажу


  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 27 февраля 2012 г. 16:15, спустя 2 часа 6 минут 8 секунд

    Так, поторопился я с вопросами. Метод __get реализовал, не так всё и сложно. Плохо только то что с поиском информации большие проблемы - её нету )

    В любом случае - попрошу отметится в теме тех кто может чем-нибудь помочь - вдруг возникнет таки надобность в помощи сообщества.
  • mario

    Сообщения: 6067 Репутация: N Группа: Джедаи

    Spritz 27 февраля 2012 г. 17:03, спустя 47 минут 19 секунд

    Плохо только то что с поиском информации большие проблемы - её нету )

    ну так теперь возьми и приведи свои куски кода, что бы в дальнейшем люди с поиска видели хоть что-то.
  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 27 февраля 2012 г. 21:26, спустя 4 часа 23 минуты 36 секунд

    там собственно то кода всего ничего.

    вот например реализация __get():



    PHP_METHOD(MyClass, __get) {
    char *key;
    int key_len;
    zval **value;

    if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_len)) {
    RETURN_NULL();
    }

    zval *attrs, *obj;
    obj = getThis();
    attrs = zend_read_property(Z_OBJCE_P(obj), obj, "attrs", strlen("attrs"), TRUE, TSRMLS_C);

    if (Z_TYPE_P(attrs) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attrs), key, strlen(key) + 1)) {
    if (zend_hash_find(Z_ARRVAL_P(attrs), key, strlen(key) + 1, (void**)&value) == SUCCESS) {
    *return_value = **value;
    zval_copy_ctor(return_value);
    }
    } else {
    zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 1, TSRMLS_C,
    "unknown field \"%s\"", key);
    }
    }



    считываем поле, если ключ существует, то возвращаем, иначе бросаем исключение.

    аналогично пытаюсь реализовать __set():


    char *key;
    int key_len;
    zval *value;

    if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &key, &key_len, &value)) {
    RETURN_NULL();
    }

    zval *attrs, *obj;
    obj = getThis();
    attrs = zend_read_property(Z_OBJCE_P(obj), obj, "attrs", strlen("attrs"), TRUE, TSRMLS_C);

    if (Z_TYPE_P(attrs) == IS_ARRAY && zend_hash_exists(Z_ARRVAL_P(attrs), key, strlen(key) + 1)) {
    zend_hash_update(Z_ARRVAL_P(attrs), key, strlen(key) + 1, (void*)&value, sizeof(zval*), NULL);
    } else {
    zend_throw_exception_ex(zend_exception_get_default(TSRMLS_C), 1, TSRMLS_C,
    "unknown field \"%s\"", key);
    }


    Но я не уверен, что я правильно использую zend_hash_update. Дело в том, что когда я таким образом обновляю значение поля, а потом дальше по коду (аналогично коду из метода __get()) делаю проверку - получаю что оно обновилось, но на стороне php скрипта я наблюдаю что в поле записывается NULL. Притом что я уверен что zval *value приходит корректно.

    у меня самого пока мало инфы чтобы выложить её здесь для помощи тем кто пойдёт по моим стопам. вот когда у меня получится сделать то что я задумал, тогда и поделюсь
  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 28 февраля 2012 г. 9:40, спустя 12 часов 13 минут 35 секунд

  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 28 февраля 2012 г. 13:56, спустя 4 часа 16 минут 2 секунды

    Супер, на SO мне ответили. Я и сам пробовал такое решение, вот только упускал копирование конструктора.

    Сделал замеры предварительные, гонял туда сюда считывание/запись числа в свойство класса. Результаты суперские, нативный класс показывает выигрыш в скорости до трех(!) раз.
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 28 февраля 2012 г. 13:59, спустя 2 минуты 39 секунд

    зачем этот бред, я даже спрашивать не стану :-)
    Сапожник без сапог
  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 28 февраля 2012 г. 14:00, спустя 1 минуту 14 секунд

    Бред - это монолог, который у меня получился? )) Или сама идея перенесения кода в модуль?
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 28 февраля 2012 г. 14:01, спустя 1 минуту 5 секунд


    Бред - это монолог, который у меня получился? )) Или сама идея перенесения кода в модуль?
    да коенчно
    Сапожник без сапог
  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 28 февраля 2012 г. 14:04, спустя 3 минуты 12 секунд

    Во фреймворке, используемом в компании где я работаю на продакшне - есть класс, реализующий показанную мной функциональность. У него много наследников, и профайлер показал что __get и __set у родителя - довольно частая операция. Я вынес их в модуль и получил профит по скорости.

    Да и вообще, вынос критических к скорости операция - вполне разумно и оправдано.
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 28 февраля 2012 г. 14:06, спустя 1 минуту 33 секунды

    понятно. я уж было подумал что ты новое чтото так писать собрался :)
    Сапожник без сапог
  • Ivan

    Сообщения: 1316 Репутация: N Группа: Адекваты

    Spritz 28 февраля 2012 г. 14:42, спустя 36 минут 17 секунд

    А почему бы тупо критические места не написать на C/C++?
    Придумывают люди себе геморрой
  • newmindcore

    Сообщения: 10 Репутация: N Группа: Кто попало

    Spritz 28 февраля 2012 г. 14:49, спустя 6 минут 51 секунду

    Ivan, странный какой-то комментарий у тебя вышел. Я итак вынес критическое место в C. Не в виде отдельных либы/приложения, которые всё равно как-то привязать надо к коду и вызывать, а в виде родного для php расширения.
    Обрати внимание - мне надо было реализовать php класс (именно php, со спецификой использования магических методов).
    Если бы какую хэш функцию или ещё что-нить - что не имеет напрямую отношения к php понадобилось вынести, тогда другой разговор, это делается в standalone либах.

Пожалуйста, авторизуйтесь, чтобы написать комментарий!