Проверьте, не определены ли элементы массива из XSUB

Я пытаюсь проверить, является ли элемент массива undef из XSUB следующим образом:

void
print_array(array)
    AV *array

    PREINIT:
        int len;
        SV **sv_ptr;
        SV *sv;
        int i;

    CODE:
        len = av_len(array) + 1;
        printf("[");
        for (i = 0; i < len; i++) {
            sv_ptr = av_fetch( array, i, 0 );
            if (!sv_ptr) {
                printf("empty");
            }
            else {
                sv = *sv_ptr;
                if (sv == &PL_sv_undef) {
                    printf("undef");
                }
                else {
                    printf("*");
                }
            }

            if (i < (len - 1)) {
                printf(", ");
            }
        }

        printf("]\n");

Если я запускаю эту подпрограмму из Perl-скрипта:

use strict;
use warnings;
use ArrayPrint;

my $array = [];
$array->[4] = undef;
ArrayPrint::print_array($array);

Результат:

[empty, empty, empty, empty, *]

Почему последний элемент не показывает undef?


person Håkon Hægland    schedule 23.04.2020    source источник


Ответы (1)


SV может содержать неопределенное значение, но все же быть другим SV, чем PL_sv_undef. Вам нужно заменить тест PL_sv_undef на

SvGETMAGIC(sv);
if (!SvOK(sv)) { printf "undef" } else { printf "*" }
person Dave Mitchell    schedule 23.04.2020
comment
Почему важно сначала запустить SvGETMAGIC()? - person Håkon Hægland; 23.04.2020
comment
@ Håkon Hægland, потому что вы никогда не узнаете значение var с get magic до того, как получите его. демо (SvGETMAGIC ничего не делает, если переменная не имеет магии получения.) - person ikegami; 23.04.2020
comment
(и SvOK не просто выполняет сам SvGETMAGIC, потому что это затруднило бы для каждой perl-операции запуск магии только один раз для каждого аргумента) - person ysth; 23.04.2020