tfoertsch has asked for the wisdom of the Perl Monks concerning the following question:

Hi,

I have a bunch of C-strings with or without a trailing \0. I want to make them available in Perl as read-only variables. When the perl SV is destroyed the string must not be freed obviously.

Do I need to make those variables magic? Or is there a simpler way?

If I need magic, do I need to implement all of the 8 MGVTBL members? What if some of them are NULL?

I think I need only an svt_free function that does:

SvPVX(var) = NULL; SvCUR(var) = 0;

Is this correct?

I have read somewhere that perl strings do not need the trailing \0 byte. But for some reasons it is normally allocated. Why? Is it necessary? What can happen if there is no trailing \0?

Thanks,
Torsten

Replies are listed 'Best First'.
Re: readonly access to C-level strings
by ambrus (Abbot) on Jul 02, 2009 at 11:01 UTC

    perlguts tells you about whether the tailing nul byte is needed or not.

      So, it is needed only to be able to pass the pure pointers without the length to other C-functions, right?
Re: readonly access to C-level strings
by jettero (Monsignor) on Jul 02, 2009 at 11:05 UTC
    Any string available to Perl will have been copied into a Perl structure. You can free the C structure all you like. I don't think you'll succeed in making it read-only, but it certainly won't affect the string the C code points to.

    -Paul

      What I want to avoid is exactly this copying. The strings are located in a mem segment that is mmapped read-only. So, there is no way for them to be changed and hence no need to be copied.

        hence no need to be copied.

        No, there is a need: For Perl to see them.

        The buffers of Perl strings are subject to modification and freeing at any time. It *might* be possible to tell Perl the PV associated with a scalar can't be changed, but

        • there's no way to tell Perl to use a existing memory block for the string buffer of a string, and
        • there's no way to tell Perl the string buffer of a string can't be freed.
Re: readonly access to C-level strings
by Anonymous Monk on Jul 02, 2009 at 11:24 UTC
[SOLUTION] readonly access to C-level strings
by tfoertsch (Beadle) on Jul 03, 2009 at 07:29 UTC
    Recently I asked about how to provide read-only access to a bunch of C-level strings without copying them.

    So, this is how it works:

    sv=newSV(0); SvUPGRADE(sv, SVt_PV); SvPOK_only(sv); SvPV_set(sv, pointer); SvLEN_set(sv, 0); SvCUR_set(sv, length); SvREADONLY_on(sv);

    pointer is the address of the first byte of the string and length its length.

    The trick is the SvLEN_set(sv, 0) statement. It prevents Safefree() to be called on the pointer during destruction of the SV.

    If you work with such variables and want to avoid copying even further in the perl code you have to be quite careful. A simple $x=$y or sub x {my ($x)=@_;} x($y) where $y is such a read-only SV will copy it.

    So, I found the best way to avoid copying is to work with references: $x=\$y; substr $$x, ... or sub x {my ($x)=@_; substr $$x, ...} x(\$y)

    Torsten

        ...or an update to the original post.

        ...roboticus