rb_iv_get и rb_iv_set VS. Data_Wrap_Struct для создания пользовательских классов - PullRequest
3 голосов
/ 15 августа 2011

rb_iv_get и rb_iv_set VS. Data_Wrap_Struct для пользовательских calsses

Итак, читая API расширения Ruby, я обнаружил Data_Wrap_Struct, который преобразует указатель в объект Ruby (верно?). Тем не менее, когда я пытался использовать это, я продолжал получать случайные ошибки и еще много чего, поэтому я как бы переключался на что-то вроде:

void Init_custom() {
    //cCustom declared as VALUE higher in the code
    cCustom = rb_define_class("Custom", T_OBJECT);
    rb_define_method(mTester, "initialize", init_Custom, 1);
    rb_define_method(mTester, "someValue", someValue_get_Custom, 0);
    rb_define_method(mTester, "someValue=", someValue_set_Custom, 1);
    //And so on.
}

Во-вторых, someValue_get_Custom и someValue_set_Custom будут:

VALUE someValue_get_Custom(VALUE self) {
    return rb_iv_get(self, "@someValue")
}

VALUE someValue_set_Custom(VALUE self, VALUE val) {
    return rb_iv_set(self, "@someValue", val) //or do I have to do return val;?
}

Другой вариант - создать версию C на 1015 *, которая сделает код немного короче и DRYer, но он все равно будет частью плана B (с использованием rb_iv_ set / get).


Теперь мне бы очень хотелось выяснить, как использовать Data_Wrap_Struct, поскольку у меня есть подозрения, что это может быть быстрее, чем при использовании rb_iv_set и rb_iv_get, но если это не то, что я думаю, тогда я Придется прибегнуть к плану Б.

Итак, я думаю, реальный вопрос:

Что точно делает Data_Wrap_Struct и как его правильно использовать или just использует без ошибок .


О, и я почти забыл, еще несколько вопросов, связанных с Data_Wrap_Struct:

Что именно делает параметр mark (функция)? В нем говорится, что для параметра mark нужно установить значение 0, если на объект нигде не ссылаются, но что, если на него ссылаются где-то (возможно, RArray)?

Во-вторых, будет ли свободный параметр (также функция) простой функцией, которая освобождает выделенную память для этого объекта?

И что-нибудь передается этим двум функциям сборщиком мусора, может быть, VALUE self?

Спасибо!

1 Ответ

4 голосов
/ 16 августа 2011

Это много вопросов, я постараюсь ответить на те, на которые я могу ответить, в нескольких предложениях.

Думайте о Data_Wrap_Struct как о тонкой оболочке Ruby, которая видна в Ruby как "обычный объект, но на самом деле несет в себе ссылку на структуру C (может быть что угодно в теории, но имеет смысл только для сложных типов).Идея заключается в том, что таким образом вы можете присоединить структуру к объекту Ruby и в любое время иметь доступ к данным структуры всякий раз, когда Ruby запрашивает их, отправляя сообщения этому объекту-оболочке.В C вы затем извлекаете данные из структуры, превращаете их во что-то рубиновое и передаете обратно.Или вы делаете противоположное, когда вас просят установить данные в объекте-оболочке - вы преобразуете данные Ruby в данные, соответствующие структуре.

Когда сборщик мусора решает собрать объект-оболочку, он также хочетосвободить базовую структуру C - это работа аргумента free, это указатель на функцию, которая принимает тип структуры в качестве аргумента и должна освободить память этой структуры.

markПараметр намного сложнее, я бы посоветовал вам опубликовать это как отдельный вопрос.Хорошая вещь: в большинстве случаев она вам не понадобится.

rb_iv_get, rb_iv_set, а также rb_ivar_get и rb_ivar_set предназначены для совершенно другой цели.Они устанавливают переменные экземпляра вашего объекта Ruby, и я предполагаю, что именно это вы и искали.Дело в том, что вы получаете / устанавливаете VALUE s здесь, то есть вы работаете здесь с объектами Ruby вместо простых типов C.

Вам не нужно писать свою версию C attr_accessor,это уже там: rb_attr.

Подводя итог: Data_Wrap_Struct оборачивает объект контейнера над вашей структурой C, но кроме этого пока не предоставляет никаких функциональных возможностей.Вы должны использовать rb_attr в вашем Init методе, если вы хотите иметь attr_accessor функциональность.Используйте rb_iv*, если вы действительно хотите установить или получить переменные экземпляра явно.


Я согласен с тем, что не хватает определенного ресурса для написания расширений C для Ruby.Есть много сообщений в блоге, хотя.Исходя из своего собственного опыта, я, вероятно, начну с Pickaxe PDF, который Сераб упомянул в комментариях, и в источниках Ruby есть довольно аккуратное введение (README.EXT).После этого лучшее, что вы можете сделать, - это посмотреть на расширения в каталоге ext в источниках Ruby.Выберите тот, с кем вы знакомы или чей функционал вам нравится, и поиграйте с ним.Всегда имейте под рукой исходный код Ruby.Если вы не знаете, что делает конкретная функция, посмотрите ее объявление в источниках, чтобы хотя бы понять, что она делает.Вам не нужно понимать все это с первого взгляда, но, как правило, это дает вам достаточно для продолжения работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...