perlguts - Введение в Perl API

ОПИСАНИЕ

Этот документ пытается описать использование Perl API и дать некоторую информацию об основах работы ядра Perl. Он далеко не полон и, возможно, содержит много ошибок. Пожулайста, обращайтесь с любыми вопросами или коментариями к автору статьи.

Переменные

Типы данных

В Perl есть три определения типа для обработки трех основных типо данных Perl: Perl has three typedefs that handle Perl's three main data types:

SV  Скаляр
AV  Массив
HV  Хэш

Для каждого определения имеются спецефические процедуры для манипуляции различными типами данных.

Что такое "IV"?

Perl использует typedef IV для определения обычного знакового integer,что гарантирует достаточный размер для хранения указателя (и самого integer). Также есть определение UV, то есть просто беззнаковый IV.

Perl также использует два специальных определения типа I32 и I16, длина которых всегда ьудет как минимум 32 и 16 бит, соответственно. (Аналогично есть U32 и U16.) Обычно эти типы равны точно 32 и 16 битам, но на Crays они оба будут занимать 64 бита.

Работа с SV

SV можно создать и инициализировать одной командой. ПОддерживается загрузка пяти типов значений: integer (IV), беззнаковый integer (UV), double (NМ), строка (PV) и другой скаляр (SV). ("PV" означает "Pointer Value". Вам может показаться, что для указателя только на строки это неверное название. Однако в PV возможно хранить что то другое, например, указатель на массив UV. Но при этом надо проявлять осторожность, так как большая часть внутренних механизмов ожидает в PV только строку. Например, часто происходит автоматическое добавление NUL. Использование PV с не-строками описано здесь только в этом параграфе.)

Семь процедур:

SV*  newSViv(IV);
SV*  newSVuv(UV);
SV*  newSVnv(double);
SV*  newSVpv(const char*, STRLEN);
SV*  newSVpvn(const char*, STRLEN);
SV*  newSVpvf(const char*, ...);
SV*  newSVsv(SV*);

STRLEN имеет тип integer (Size_t, обычно определяемый в config.h как size_t), достаточно большой для хранения любой строки, которую может обработать Perl.

В редких случаях, когда требуется более сложная инициализация, можно использовать newSV(len) для создания пустого SV. При len, равном нулю, возвращается пустой SV типа NULL, иначе возвращается SV типа PV с выделенными len + 1 (для С<NUL>) байтами памяти, доступными через SvPVX. В обоих случаях SV имеет undef значение.

SV *sv = newSV(0);   /* память не выделяется */
SV *sv = newSV(10);  /* выделяется 10 (+1) байт неинициализированной
                      * памяти allocated */

Для изменения значения уже существующего SV существует восемь функций:

void  sv_setiv(SV*, IV);
void  sv_setuv(SV*, UV);
void  sv_setnv(SV*, double);
void  sv_setpv(SV*, const char*);
void  sv_setpvn(SV*, const char*, STRLEN)
void  sv_setpvf(SV*, const char*, ...);
void  sv_vsetpvfn(SV*, const char*, STRLEN, va_list *,
                                                SV **, I32, bool *);
void  sv_setsv(SV*, SV*);

обратите внимание, что можно либо передавать длину строки в sv_setpvn, newSVpvn и newSVpv, либо дать Perl вычислить её в sv_setpv или передавая 0 вторым агрументом newSVpv. Однако будьте внимательны, так как для вычисления длины используется strlen, которая зависит от наличия завершающего NUL и отсутствия других NUL внутри строки.

Аргументы sv_setpvf обрабатываются подобно аргументам sprintf, значением будет отформатированный результат.

sv_vsetpvfn является аналогом vsprintf, но позволяет определять либо указатель на список различных аргументов, либо адрес и длину массива SV. Последний аргумент, указатель на boolean, при возврате содержит true, если при форматировании использовалась локале-специфичная информация и поэтому содержимое строки ненадежно (см. perlsec). Если эта информация не важна, передавайте NULL. Также обратите внимание, что требуется определять длину строки формата.

Функции sv_set*() не являются достаточно обобщенными для оперирования значниями с "магией". Смотрите "Magic Virtual Tables" далее.

Во всех SV, хранящих строки, строки должны завершаться символом NUL, иначе есть риск падения в дамп или порчи программы из кода, который передает их в функции C или системные вызовы, ожидающие завершающиеся NUL строки. По этой причине собственные функции Perl обычно добавляют завершающий c<NUL>. Тем не менее, нвдо быть очень осторожным, передавая хранящиеся в SV строки в C-функии ил системные вызовы.

Для доступа к действиельному содержимому SV могут использоваться макросы:

SvIV(SV*)
SvUV(SV*)
SvNV(SV*)
SvPV(SV*, STRLEN len)
SvPV_nolen(SV*)

которые автоматически преобразуют действительный типа скаляра в IV, UV, double или строку.

SvPV помещает длину возвращаемой строки в переменную len (это макрос, поэтому вам не нужно писать &len). Если длина вам не нужна, используйте SvPV_nolen. По историческим причинам в этом случае используется макрос SvPV с глобальной переменной PL_na. Но это может быть довольно неэффективно, поскольку PL_na должнв быть доступна в локальной памяти потока в потоковом Perl. В любом случае помните, что в Perl позволяет хранить в строках произвольные данные, в которых могут быть NUL внутри и не быть завершающего NUL.

Также помните, что в C нельзя безопасно написать foo(SvPV(s, len), len);. Это может проглотить ваш компилятор, но не проглотить другие. Разбивайте такую запись на отдельные иструкции:

SV *s;
STRLEN len;
char *ptr;
ptr = SvPV(s, len);
foo(ptr, len);

Если вы хотите узнать, является ли скалярне значение TRUE, используйте:

SvTRUE(SV*)

Хотя Perl автоматически наращивает строки, если вам понадобилось принудительно выделить большее количество памяти для SV, можно воспользоваться макросом

SvGROW(SV*, STRLEN newlen)

который определит, нужно ли дополнительное выделение. Если да, будет вызвана функция sv_grow. Обратите внимание, что можно только увеличивать, не уменьшать, размер памяти для SV в SvGROW, и что при выделении памяти место для завершающего NUL не добавляется автоматически (строковые функции самого Perl обычно используют SvGROW(sv, len + 1)).

Если вы хотитите записать в буфер существующего SV и установить это значение, как строку, используйте SvPV_force() или однин из ее вариантом, чтобы принудить SV быть PV. При этом из SV будут удалены любые не приdовдимые к строке типы но сохранится содержимое. Этот функционал можно использовать ,например, при добавлении данных в буфер из функций API без дополнительного копирования:

(void)SvPVbyte_force(sv, len);
s = SvGROW(sv, len + needlen + 1);
/* 
   Нечто, что изменяет до needlen байтов с s+len, но байты newlen
   something that modifies up to needlen bytes at s+len, but
   modifies newlen bytes
     eg. newlen = read(fd, s + len, needlen);
   в этом примере игнорируются ошибки
   ignoring errors for these examples
 */
s[len + newlen] = '\0';
SvCUR_set(sv, len + newlen);
SvUTF8_off(sv);
SvSETMAGIC(sv);

Если уже есть данные в памяти или вы хотите, что бы код был проще, используйте один из вариантов sv_catpvn(). Чтобы вставить данные внутрь строки, используйте sv_insert() или sv_insert_flags().

Если не нужно сохранять текущее содержимое SV, избежать копирования можно:

sv_setpvn(sv, "", 0);
s = SvGROW(sv, needlen + 1);
/* something that modifies up to needlen bytes at s, but modifies
   newlen bytes
     eg. newlen = read(fd, s. needlen);
 */
s[newlen] = '\0';
SvCUR_set(sv, newlen);
SvPOK_only(sv); /* also clears SVf_UTF8 */
SvSETMAGIC(sv);

Повторим, что если у вас уже есть данные в памяти или вам не нравится сложность кода в пример выше, используйте sv_setpvn().

Если есть буфер, выделенный с помощью Newx() и вы хотите установить его, как значение SV, используйте sv_usepvn_flags(). Чтобы избежать реаллокации буфера при добавлении завершающего NUL, длжны быть соблюдены некоторые требования:

Newx(buf, somesize+1, char);
/* ... заполняем буфер ... */
buf[somesize] = '\0';
sv_usepvn_flags(sv, buf, somesize, SV_SMAGIC | SV_HAS_TRAILING_NUL);
/* теперь буфер принадлежит perl, не освобождайте его */

Макросы для определения того, что Perl думает о типе данных в SV:

SvIOK(SV*)
SvNOK(SV*)
SvPOK(SV*)

Макросы для получение и установка текущей длины сроки в SV:

SvCUR(SV*)
SvCUR_set(SV*, I32 val)
Также можно получить указатель на конец строки:

SvEND(SV*)

Но имейте ввиду, что последнии три макроса правомерны только если SvPOK возвращает истину.

Макросы для добавления чего-либо в конец сроки в SV:

void  sv_catpv(SV*, const char*);
void  sv_catpvn(SV*, const char*, STRLEN);
void  sv_catpvf(SV*, const char*, ...);
void  sv_vcatpvfn(SV*, const char*, STRLEN, va_list *, SV **,
                                                         I32, bool);
void  sv_catsv(SV*, SV*);

Первая функция вычисляет длину добавляемой строки с помощью strlen. Во вторую вы передаете длину сами. Третья обрабатывает аргументы подобно sprintf и добавляет отформатированный ресультат. Четвертая работает подобно vsprintf. Вместо аргумента va_list она может получать массив SV и его длину. Пятая функция расширяет строку в первом SV строкой из второго SV. Также она заставляет второй SV интерпретироваться как строка.

Функции семейства sv_cat*() недостаточно общие, чтобы работать с значениями с "магией". Смотрите секцию "Magic Virtual Table" далее.

Если известно имя переменной, можно получить указатель на SV:

SV*  get_sv("package::varname", 0);

Если переменная не существует, возвращается NULL.

Следующий вызов позволяет узнать, действительно ли определена переменная:

SvOK(SV*)

Скалярное значение undef хранится в экземпляре SV с именем PL_sv_undef.

Её адрес может использоваться там, где необходим SV. Убедитесь, что вы не пытаетесь сравнить случайное sv c PL_sv_undef. Например, при взаимодействии с кодом Perl это работает корректно:

foo(undef)

а это нет:

$x = undef;
foo($x);

Так что повторим, что для проверки определенности всегда используйте SvOK().

Также будьте внимательны, используя &PL_sv_undef в качестве значений AV или HV (см. "AVs, HVs и неопределенные значения").

Есть еще два значения PL_sv_yes и PL_sv_no, которые содержат логические TRUE и FALSE, соответственно. Также как и в случае PL_sv_undef должны использоваться их адреса, когда требуется.

Вы ошибетесь, если решите что (SV *) 0 то же самое, что и &PL_sv_undef. Возьмем код:

SV* sv = (SV*) 0;
if (I-am-to-return-a-real-value) {
        sv = sv_2mortal(newSViv(42));
}
sv_setsv(ST(0), sv);

Этот код пытается вернуть новый SV (содержащий 42), если нужно реальное значение, или undef в ином случае. Вместо этого он вернет NULL, что где-нибудь ниже приведет к нарушению сегментации, ошибке шины или просто странным Замените ноль в первой строке на &PL_sv_undef и все станет нормально.

Для освобождения ранее созданного SV служит SvREFCNT_dec(SV*). Обычно этот вызов не требуется (смотрите "ПОдсчет Ссылок и Смертность").

Смещения

Для эффективного удаления символов из начала строки используется sv_chop; она принимает SV и указатель на какое-либо место внутри PV, и отбрасывает все до этого указателя. Эффективность достигется небольшим хаком: вместо реального удаления символов sv_chop устанавливает флаг OOK (offset OK). чтобы другие функции могли понять, что используется смещение. Указатель PV (SvPVX)перемещается вперед на число отброшенных символов, и соответствующим образом устанавливаются SvCUR и SvLEN. (Часть места между старым и новым PV используется для хранения числа отрезанных байтов)

С этого момента начало лежащего в памяти буфера находится по адресу SvPVX(sv) - SvIV(sv) и PV указывает куда то в его середину.

Лучше продемонстрировать сказанное примером. Обычно механизм copy-on-write препятствует использованию этого хака из оператора замены, но если вы сможете смастерить троку, на которой copy-on-write невозможен, то получится увидеть действии хака. В текущей реализации финальный байт строкового буфера используется в качестве счетчика ссылок copy-on-write. Если буфер недостаточно большой, copy-on-write пропускается. Возьмем для начала пустую строку:

% ./perl -Ilib -MDevel::Peek -le '$a=""; $a .= ""; Dump $a'
SV = PV(0x7ffb7c008a70) at 0x7ffb7c030390
  REFCNT = 1
  FLAGS = (POK,pPOK)
  PV = 0x7ffb7bc05b50 ""\0
  CUR = 0
  LEN = 10
Обратите внимание, что LEN равно 10. (На вышей платформе может быть другое значение.) Увеличим
строку до длины, на единицу меньше 10, и сделаем замену:

% ./perl -Ilib -MDevel::Peek -le '$a=""; $a.="123456789"; $a=~s/.//; Dump($a)'
SV = PV(0x7ffa04008a70) at 0x7ffa04030390
  REFCNT = 1
  FLAGS = (POK,OOK,pPOK)
  OFFSET = 1
  PV = 0x7ffa03c05b61 ( "\1" . ) "23456789"\0
  CUR = 8
  LEN = 9

% ./perl -Ilib -MDevel::Peek -le '$a=""; $a.="123456789"; $a=~s/.//; Dump($a)'
SV = PV(0x7ffa04008a70) at 0x7ffa04030390
  REFCNT = 1
  FLAGS = (POK,OOK,pPOK)
  OFFSET = 1
  PV = 0x7ffa03c05b61 ( "\1" . ) "23456789"\0
  CUR = 8
  LEN = 9

В OFFSET показано число отрезанных байтов. Часть строки между "реальным" и "фальшимым" началом показана в скобках, и значения SvCUR и SvLEN отражают фальшивое начало строки, а не реальное. (Первый символ строкового буфера изменяется на "\1", поскольку текущая реализация сохраняет там счетчик смещения. Замена такого поведения является темой дискурсий.)

Нечто подобное хаку со смещением применяется и c типом AV для реализации эффективного сдвига и замены в начале массива; в то время, как AvARRAY указывает на первый элемент массива, видимого в Perl, AvALLOC указывает на реальное начало C-массива. Обычно они равны, но операция shift может увеличить на единицу AvARRAY и уменьшить на единицу AvFILL и AvMAX. Опять таки, местонахождение реального начала массива C вступает в игру только при освобождении массива. Смотрите av_shift в ac.c.

Что на Самом Деле Хранится в SV?

Напомним, что для определения типа скаляра обычно используются макросы Sv*OK. Поскольку скаляр может быть и числом и строкой, эти маркросы почти вегда возвращают TRUE, а при вызове SV*V произойдет соответствующее преобразование строки в integer/double и наоборот.

Если вам на самом деле необходимо знать, находится ли в вашем SV interer, double или указатель на сроку, вместо Sv*OK используйте следующие три макроса:

SvIOKp(SV*)
SvNOKp(SV*)
SvPOKp(SV*)

Они сообщат вам, что в действительности хранится в SV. "p" здесь означает private.

Есть несколько мест, где приватные и публичные флаги могут отличаться. Например, в perl 5.16 и более ранних версиях в слоте IV связанного SV могло находиться допустимое значение (SvIOKp - истина), но для доступу к данным необходимо использовать процедуру FETCH, а не получать их напрямую, поэтому SvIOK - ложь. (Начиная с perl 5.18, связанные скаляры используют флаги так же, как ине связанные.) Другой пример, это числовое преобразование с потерей точности: для 'lossy' значений устанавливается только приватный флаг. Поэтому, при преобразовании NV в IV с потерей точности, будут установлены флаги SvIOKp, SvNOKp и SvNOK , но не SvIOK.

В общем случае, однако, лучше использовать макросы Sv*V.

Работа с AV

Создать и загрузить AV можно двумя способами. Первый метода создает пустое AV:

AV* newAV();

Второй метод создает AV и инициализирует его значениями SV:

AV* av_make(SSize_t num, SV **prt)

Второй аргумент указывает на массив из num SV*. Как только массив создан, эти SV можно уничтожить, если хочется.

Следующие опреации доступны после создания AV:

void  av_push(AV*, SV*);
SV*   av_pop(AV*);
SV*   av_shift(AV*);
void  av_unshift(AV*, SSize_t num);

Все эти опреации, вероятно, очевидны, за исключением av_unshift. Эта процедура добавляет num элементов со значением undef в начало массива. Затем вы должны присвоить значения этим элементам с помощью описанной ниже av_store.

Еще несколько функций:

SSize_t av_top_index(AV*);
SV**    av_fetch(AV*, SSize_t key, I32 lval);
SV**    av_store(AV*, SSize_t key, SV* val);

av_top_index возвращает наибольшее значение индекса массива (то же самое делает $#array в Perl), или -1, если массив пуст.

av_fetch вернет значение по индексу key, но также, если параметр lval не равен нулю, сохранит неопределенное значение по этому же индексу. av_store сохраняет val по индексу key, но не увеличивает счетчик ссылок val. Об этом должнв позаботиться вызывающая сторона, и если av_store вернул NULL, вызывающий дожне уменьшить счетчик ссылок для избежания утечки памяти. Заметьте, что av_fetch и av_store возвращают SV**, а не SV*.

Еще функции:

void  av_clear(AV*);
void  av_undef(AV*);
void  av_extend(AV*, SSize_t key);

av_clear удаляет все елементы из массива AV*, но не удаляет сам массив. av_undef удалит все жлементы плюс сам массив. av_extend расшириряет массив, так что он будет содержать как минимум key+1 элементов. Если key+1 меньше текущей длины массива, av_extend ничего не делает.

Если вам известно имя переменной, можно получить указатель на AV:

AV*  get_av("package::varname", 0);

Если переменная не существует, возвращается NULL.

В секция "Понимание Магии Связанных Хэшей и Массивов" содержится больше информации об использовании функций доступа со связанными массивами.

Работа с HV

Для создания HV используется следующаяч процедура:

HV* newHV();

После создания на HV возможны следующие операции:

SV**  hv_store(HV*, const char* key, U32 klen, SV* val, U32 hash);
SV**  hv_fetch(HV*, const char* key, U32 klen, I32 lval);

Параметр klen содержит длину передаваемого ключа (заметьте, что в klen нельзя передавать 0, предлагая Perl самому вычислить длину ключа). Аргумент val содержит указатель типа SV на сохраняемый скаляр, и в hash - предварительно вычесленный хэш ключа, или 0, чтобы hv_store вычислила его сама. Параметр lval используется для указания, что операция получения в действительности является частью операции сохранения, в этом случае в HV будет добавлено новое неопределенное значение по заданному ключу, и hv_fetch вернет его, как если оно уже существовало.

Помните, что hv_store и hv_fetch возвращают SV**, а не просто SV*. Для доступа к скалярному значению необходимо разименововать вернувшееся значение. Однако, сначала нужно убедиться, что оно не NULL.

Первая из следующих двух функций проверяет существование записи в хэш-таблице, вторая удаляет запись:

bool  hv_exists(HV*, const char* key, U32 klen);
SV*   hv_delete(HV*, const char* key, U32 klen, I32 flags);

Если flags не включает флаг G_DISCARD, hv_delete создаст и вернет смертную копию удаляемого значения.

И еще функции:

void   hv_clear(HV*);
void   hv_undef(HV*);

Как и парные AV функции, hv_clear удаляет все записи хэш-таблицы, но не удаляет ее саму. hv_undef удаляет и записи и саму таблицу.

Perl хранит действительные данные в связанном списке структур типа typedef HE. Структура содержит указатели на ключ и значение (плюс дополнительный административный довесок). Ключ - указатель на строку; значением является SV*. Однако, как только у вас появляется HE*, для получения ключа и значения используйте определенные ниже процедуры:

    I32    hv_iterinit(HV*);
            /* Подготавливает точку старта для прохода по хэш-таблице */
    HE*    hv_iternext(HV*);
            /* Получает следующую запись и возвращает указатель на 
               структуру, хранящую ключ и значение */
    char*  hv_iterkey(HE* entry, I32* retlen);
            /* Получает ключ из структуры HE, а также возвращает длину строки с ключом */
    SV*    hv_iterval(HV*, HE* entry);
            /* Возвращает указатель на SV значения из структуры HE */
    SV*    hv_iternextsv(HV*, char** key, I32* retlen);
            /* Удобная процедура, комбинирующая hv_iternext, hv_iterkey и hv_iterval.
               Ключ и его длина возвращаются в аргументах key и retlen, значение 
               возвращается через SV* 
	        */

Если известно имя переменной, можно получить указатель на HV:

SV*  get_hv("package::varname", 0);

Если переменная не существует, возвращается NULL.

Алгоритм хеширования определен через макрос PERL_HASH:

PERL_HASH(hash, key, klen)

Конкретная реализация этого макроса зависит от архитектуры системы и версии Perl, а возвращаемое значение может меняться при запуске интерпретатора, так что оно действительно только на время жизни одного процесса Perl.

В секция "Понимание Магии Связанных Хэшей и Массивов" содержится больше информации об использовании функций доступа со связанными массивами.

Расширенное API Хэшей

Начиная с версии 5.004 доступны следующие функции:

HE*     hv_fetch_ent  (HV* tb, SV* key, I32 lval, U32 hash);
HE*     hv_store_ent  (HV* tb, SV* key, SV* val, U32 hash);

bool    hv_exists_ent (HV* tb, SV* key, U32 hash);
SV*     hv_delete_ent (HV* tb, SV* key, I32 flags, U32 hash);

SV*     hv_iterkeysv  (HE* entry);

Обратите внимание, что эти функции принимают ключ в виде SV*, что упрощает написание расширений, работающих с структурой хэша. Также они позволяют передавать SV* ключей в функции tie, не заставляя вас стрингифицировать ключи, в отличии от предыдущего набора функций.

Они также возвращают и принимают запись хэша целиком (HE*), что делает их более эффективными (поскольку не нужно каждый раз вычислять хэш для отдельных строк). Смотрите perlapi для детального описания.

Для доступа к содержимому записей хэша всегда должны использоваться описанные ниже макросы. Обратите внимание на то, что в аргументы этих макросов простые переменные, так как они могут определяться более одного раза. Смотрите perlapi для детального описания этих макросов.

HePV(HE* he, STRLEN len)
HeVAL(HE* he)
HeHASH(HE* he)
HeSVKEY(HE* he)
HeSVKEY_force(HE* he)
HeSVKEY_set(HE* he, SV* sv)

Далее определяются два низкоуровневых макроса, но они должны использовать только при работе с ключами, не являющимися SV*:

HeKEY(HE* he)
HeKLEN(HE* he)

Заметьте, что за увеличение счетчика ссылок val отвечает вызывающая строна,Ю так как hv_store и hv_store_ent не инкрементируют его. Если эти фукции возвращают NULL, вызывающему обычно нужно декрементировать счетчик ссылок val, дабы избежать утечки памяти.

AV, HV и Неопределенные Значения

Иногда нужно сохранить неопределенное значение в AV или HV. Хотя возможно это нужно в редких случаях, тут есть хитрости, поскольку вам нужно используете &PL_sv_undef для задания неопределенного SV.

Например, интуицитивно кажется, что следующий XS код:

AV *av = newAV();
av_store( av, 0, &PL_sv_undef );

эквивалентен Perl коду:

my @av;
$av[0] = undef;

Это не так, к сожалению. В perl 5.18 и ниже для AV &PL_sv_undef использовался как маркер, указывающий, что элемент массива еще не инициализирован. Поэтому exists $av[0] будет истинно для Perl кода, но ложно для массива в XS коде. В perl 5.20 сохранение &PL_sv_undef создаст read-only элемент, поскольку сохраняется сам скаляр &PL_sv_undef, а не его копия.

Те же самые проблемы могут возникнуть при сохранениии &PL_sv_undef в HV:

hv_store( hv, "key", 3, &PL_sv_undef, 0 );

Этого достаточно, что бы получить undef значение, но при попытке модифицировать значение key вы получите ошибку:

Modification of non-creatable hash value attempted

Мы сделаем покороче эту длинную историю, и сообщаем вам, что вы можете использовать специальные переменные &PL_sv_undef, &PL_sv_yes и &PL_sv_no с AV и HV, но вы должны быть уверены, что знаете, что делаете.

Итак, если вы хотите хранить неопределенное значение в AV или HV, вы не должны использовать &PL_sv_undef, вместо этого созайте новое неопределенное значение функцией newSV, например:

av_store( av, 42, newSV(0) );
hv_store( hv, "foo", 3, newSV(0), 0 );

Ссылки

Ссылки - это специальный тип скаляра, указывающего на другие типы данных (включая другие ссылки).

Для создание ссылки используются следующие функции:

SV* newRV_inc((SV*) thing);
SV* newRV_noinc((SV*) thing);

Аргумент thing может быть любым SV*, AV* или HV*. Функции идентичны, за исключением того, что newRV_inc увеличивает счетчик ссылок аргумента thing, а newRV_noinc нет. По историческим причинам newRV является синонимом newRV_inc.

Когда у вас есть ссылка, вы можете разименовать её, используя следующий макрос:

SvRV(SV*)

и затем, если требуется, вызвать соответствующую процедуру для преобразования возвращаемого SV* в AV* или HV*.

Макрос для определения, является ли SV ссылкой:

SvRV(SV*)

Для определения типа, на который ссылается ссылка, исследуйте возвращаемое значение следующего макроса:

SvTYPE(SvRV(SV*))

Большинство полезных типов вернется как:

< SVt_PVAV  Scalar
SVt_PVAV    Array
SVt_PVHV    Hash
SVt_PVCV    Code
SVt_PVGV    Glob (возможно файловый указатель)

Смотрите подробности в "svtype" in perlapi.

Освященные Ссылки и Объекты Класса

Ссылки используются также для поддержки объектно-ориентированного программирования. На лексиконе perl OO объект является просто ссылкой, которая была освящена (blessed) в пакет (или класс). После освящения программист может использовать ссылку для доступа к различным методам в классе.

Освятить ссылку в пакет можно следующим образом:

SV* sv_bless(SV* sv, HV* stash);

Аргумент sv должен быть ссылкой. Аргумент stash определяет, какому классу будет принадлежать ссылка. Информация о преобразовании имен классов преобразуются в стэши находится в секции "Стэши и Глобы".

/* Все еще в процессе создания */

Обновление rv до ссылки, если нужно. Создается новый SV, ссылающийся на rv. Если classname не-null, SV освещается в заданный класс. Возвращается SV.

SV* newRVrv(SV* rv, const char* classname);

Следующие три функции копируют integer, unsigned integer или double в SV, ссылка на который находится в rv. SV освящается, если classname не-null.

SV* sv_setref_iv(SV* rv, const char* classname, IV iv);
SV* sv_setref_uv(SV* rv, const char* classname, UV uv);
SV* sv_setref_nv(SV* rv, const char* classname, NV iv);

Копирование указателя (адреса, не строки!) в SV, на который ссылается rv. SV освящается, если classname не-null.

SV* sv_setref_pv(SV* rv, const char* classname, void* pv);

Копирование строки в SV, на который ссылается rv. Если length установлен в 0, Perl Perl сам вычисли длину строки. SV освящается, если classname не-null.

SV* sv_setref_pvn(SV* rv, const char* classname, char* pv,
                                                     STRLEN length);

Проверяет, является ли SV освященной в данный класс. Иерархия наследования не проверяется.

int  sv_isa(SV* sv, const char* name);

Проверить, является ли SV ссылкой на освященный объект.

int  sv_isobject(SV* sv);

Узнать, наследуется ли SV от определенного класса. SV может быть либо ссылкой на освященный объект, либо строкой, содержащей имя класса. Эта функция реализуется функциональность UNIVERSAL::isa.

bool sv_derived_from(SV* sv, const char* name);

Проверку того, что объект является наследником определенного класса, можно написать так:

if (sv_isobject(sv) && sv_derived_from(sv, class)) { ... }

Создание Новых Переменных

С помощью сдедующих трех функций можно создать новую переменную с неопределенным значением, которая будет доступна в Perl коде:

SV*  get_sv("package::varname", GV_ADD);
AV*  get_av("package::varname", GV_ADD);
HV*  get_hv("package::varname", GV_ADD);

Обратите внимание, что во втором параметре GV_ADD. Установить значение новой переменной можно с помощью соответствующие типу данных процедур.

Существуют дополнительные макросы для включения специальных возможностей, объединяемые побитовым OR с GV_ADD.

GV_ADDMULTI

Маркировать переменную, как определямую неоднократно, что подавит вывод такого предупредения:

Name <varname> used only once: possible typo
GV_ADDWARN

Вывод предупреждения:

Had to create <varname> unexpectedly

если переменная не существует до вызова функции.

Подсчет Ссылок и Смертность

Механизм сборки мусора в Perl управляется через подсчет ссылок. SV, AV или HV (далее xV для краткости) начинают жизнь со счетчиком ссылок, равным единиеце. Если счетчик ссылок какого-либо xV становится равен нулю, xV уничтожается и занимаемая им память становится доступна для повторного использования.

Обычно в perl-коде этого не бывает, пока переменная не является неопределенной, или последняя переменная, удерживающая ссылку на что-либо, не изменяется или не перезаписывается. На внутреннем уровне подсчетом ссылок можно управлять через макросы:

int SvREFCNT(SV* sv);
SV* SvREFCNT_inc(SV* sv);
void SvREFCNT_dec(SV* sv);

Есть еще одна функция, манипулирующая счетчиком ссылок своего аргумента. newRV_inc, если помните, создает ссылку на свой аргумент и, в качестве побочного эффекта, увеличивает его счетчик ссылок. Если вы не хотите увеличивать счетчик ссылок, вместо нее используйте newRV_noinc.

Например, представьте себе, что вы хотите вернуть ссылку из XSUB функции. Внутри XSUB вы создаете SV, ее счетчик ссылок изначально равен единице. Затем вы вызываете newRV_inc и передаете ей только что созданный SV. newRV_inc возвращает ссылку в новом SV, но счетчик ссылок вашего SV увеличился и стал равен двум. Далее вы возвращаете ссылку из XSUB и забываете об вашем SV. То Perl ничего не забывает! Всякий раз, когда возвращаемая ссылка уничтожается, счетчик ссылок оригинального SV уменьшается на единицу, и больше ничего не происходит. SV будет торчать в памяти, не имея никакого способа доступа, пока сам Perl не завершится. Это утечка памяти.

В данном случае правильным выбором будет использовать newRV_noinc вместо newRV_inc. Тогда после уничтожения последней ссылки счетчик ссылок SV достигет нуля и SV уничтожится, и утечки памяти не будет.

Есть несколько удобных функций, помогающих уничтожать SV. Эти функции вводят концепцию "смертости" (mortal SV). Счетчик ссылок смертного SV помечен, как подлежащий уменьшению, но реальное его уменьшение произойдет через "короткий отрезок времени". Термин "короткий отрезок времени" обычно означает выполнение одной инструкции Perl, такой, как вызов XSUB. Фактичесий момент уменьшения счетчика ссылок SV зависит от двух макросов, SAVETMPS и FREETMPS. Смотрите perlcall и perlxs.

В самом простом случае "мортализация", это отложенный вызов SvREFCNT_dec. Если, однако, вы "мортализируете" переменную дважды, в последствии счетчик ссылок также уменьшится дважды.

"Мортализация" в основном используется для SV, хранящихся в стеке Perl. Например, SV, созданный только лишь для передачи числа в вызываемую функцию, делается смертным для автоматической зачистки его после выталкивания из стека. Также, часто делается смертным результат (хранящийся на стеке) вызова XSUB.

Создание смертой переменной:

SV*  sv_newmortal()
SV*  sv_2mortal(SV*)
SV*  sv_mortalcopy(SV*)

Первый вызов создает пустое смертое SV, второй конвертирует обычное SV в смертное (и таким образом, создает отложенный вызов SvREFCNT_dec), третий создает смертную копию SV. Так как sv_newmortal дает нам новое SV без значения, значение нужно установить обычным образом через sv_setpv, sv_setiv и т.д.:

SV *tmp = sv_newmortal();
sv_setiv(tmp, an_integer);

Зачастую вместо двух C инстукций встречается следующая идиома:

SV *tmp = sv_2mortal(newSViv(an_integer));

Нужно быть внимательным при создании смертных переменных. Странные вещи могут происходить, если одно и тоже значение сделать смертым в нескольких контекстах, или или несколько раз. Думайте о "мортализации", как об откладывании вызова SvREFCNT_dec, это уменьшит количество проблем. Например, если вы знаете, что счетчик ссылок переменной достаточно велик и она переживет передачу через стек, не нужно использовать мортализацию. Если уверенности нет, вызовите sv_REFCNT_dec и sv_2mortal, или sv_mortalcopy для надежности.

Смертные функции используются не только с SV: в sv_2mortal и sv_mortalcopy можно передавать адреса AV и HV (приведя их к типу SV*).

Стеши и Глобы

Стеш - это хеш, содержащий все определенные в пакете переменные. Каждый ключ в хеше является именем символа (используется для всех объектов различных типов с тем же именем), значения в хеш-таблице представляют собой GV (Glob Value). GV, в свою очередь, содержит сылки на объекты различных типов, включая следующие (есть и другие типы):

Scalar Value
Array Value
Hash Value
I/O Handle
Format
Subroutine

Сущности пакета main находятся в глобальном хеше PL_defstash. Для доступа к элементам других пакетов используется имя пакета с добавлением символов '::'. Для элементов пакета Foo это будет Foo:: в PL_defstash. Элементы Bar::Baz находятся в стеше Baz стеша Bar.

Получить указатель на стеш конкретного пакета можно при помощи следующих функций:

HV*  gv_stashpv(const char* name, I32 flags)
HV*  gv_stashsv(SV*, I32 flags)

Первая принимает литеральную строку, вторая использует строку из SV. Помните, стеш является обычным хешом, поэтому на выходе возвращается HV*.