4

你好社区我希望我能在这里遇到一些字节字符串专家。我猜 SvPVbyte 发挥作用,但如何?

我的问题。我已经使用 Perl 在 Inline:C 中成功地解析了 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)走,而不是将它完全复制到自己的 C 数组中。

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

太感谢了。

4

1 回答 1

2
#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这里使用。
  • Anint对于返回值来说可能太小了。
  • 它不起作用,因为您正在搜索引用的字符串化。
  • 事实上,没有必要创建引用。

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));
于 2018-08-02T08:24:42.937 回答