繁体   English   中英

Perl API内联C:如何通过引用获取Perl字节字符串的substr而不复制该字符串

[英]Perl API Inline C: How to get get a substr of a Perl byte string by reference without copying that string

你好社区我希望我能在这里遇到一些字节串专家。 我猜SvPVbyte会发挥作用,但是怎么样?

我的问题。 我已经成功解析了内联中的Perl数组XYZ(在数组的散列内),其中包含示例索引6789):

$testn=pnp($lengthofXYZ,\@{$XYZ{$_}});

内联C:

int pnp ( int n, SV *vertx)
AV *arrayx;
double val_of_interest;
arrayx = (AV *)SvRV( vertx );
SV **yi;
yi = av_fetch( arrayx, 6789, 0 );
val_of_interest = SvNV( *yi );
return calculation_with_val_of_interest

这非常有效。 但是让我说在Perl $ xyz =“\\ x09 \\ x07 \\ x44 \\ xaa ......中我有一个非常长的字节字符串(大约10-50MB)......

现在我想传递一个对这个SV的引用,并在C语言中通过这个字符串以9字节步长(substr like)行走,而不是在自己的C数组中完全复制它。

步行部分:前4个字节应根据参考4字节值ABC检查,该值也应在函数调用中。 如果有必要,我可以在之前解压缩“N”这个搜索短语并用整数调用函数。 如果postition 0没有成功跳转/增加9个字节,那么如果成功,我将把找到的位置作为返回。

非常感谢。

#include <stdint.h>
#include <string.h>

void foo(SV* sv) {
    STRLEN len;
    const char *buf = SvPVbyte(sv, len);

    if (len < 4) {
        /* ... Error ... */
    }

    uint32_t sig =
        ((unsigned char)(buf[0]) << 24) |
        ((unsigned char)(buf[1]) << 16) |
        ((unsigned char)(buf[2]) <<  8) |
        ((unsigned char)(buf[3]) <<  0);

    buf += 4;
    len -= 4;
    if (sig != ...) {
        /* ... Error ... */
    }

    while (len >= 9) {
        char block[9];
        memcpy(block, buf, 9);
        buf += 9;
        len -= 9;

        /* ... Use block ... */
    }

    if (len > 0) {
        /* ... Error ... */
    }
}

[ 这是评论中问题的答案 ]

  • 永远不要使用use bytes; “强烈建议不要将此模块用于调试以外的任何其他目的。” (并且它实际上对调试没有用.Devel :: Peek更有用。)
  • 绝对没有理由在这里使用our
  • 对于返回值, int可能太小。
  • 它不起作用,因为您正在搜索引用的字符串。
  • 实际上,没有必要创建引用。

use strict;
use warnings qw( all );

use Inline C => <<'__EOS__';

SV* find_first_pos_of_43h_in_byte_string(SV* sv) {
    STRLEN len;
    const char *p_start = SvPVbyte(sv, len);
    const char *p = p_start;
    const char *p_end = p_start + len;
    for (; p < p_end; ++p) {
        if (*p == 0x43)
            return newSVuv(p - p_start);
    }

    return newSViv(-1);
}

__EOS__

my $buf = "\x00\x00\x43\x01\x01\x01";
my $pos = find_first_pos_of_43h_in_byte_string($buf);

当然,你可以简单地使用

use strict;
use warnings qw( all );

my $buf = "\x00\x00\x43\x01\x01\x01";
my $pos = index($buf, chr(67));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM