gpt4 book ai didi

Perl SV 值来自没有副本的指针

转载 作者:行者123 更新时间:2023-12-04 14:57:25 26 4
gpt4 key购买 nike

如何从空终止字符串创建 SV 值而无需复制?点赞newSVpv(const char*, STRLEN)但是没有副本并且将所有权转移到 Perl(因此 Perl 必须释放该字符串内存)。我需要这个来避免巨大的内存分配和复制。

我找到了以下示例:

SV *r = sv_newmortal();
SvPOK_on(r);
sv_usepvn_mg(r, string, strlen(string) + 1);

但是我对 XS 的内部知识并不深入,并且有一些疑问。

最佳答案

如果你想让 Perl 管理内存块,它需要知道如何重新分配和解除分配。它知道如何重新分配和解除分配的唯一内存是使用其分配器分配的内存,Newx . (否则,它必须将重新分配器和解除分配器与每个内存块相关联。)

如果无法使用 Newx 分配内存块,那么您最好的选择可能是使用 SvLEN 创建一个只读 SV设置为零。这告诉 Perl 它不拥有内存。该 SV 可以被祝福到一个具有析构函数的类中,该析构函数将使用适当的释放器释放内存。

如果可以使用 Newx 分配内存块,那么您可以使用以下内容:

SV* newSVpvn_steal_flags(pTHX_ const char* ptr, STRLEN len, const U32 flags) {
#define newSVpvn_steal_flags(a,b,c) newSVpvn_steal_flags(aTHX_ a,b,c)
SV* sv;

assert(!(flags & ~(SVf_UTF8|SVs_TEMP|SV_HAS_TRAILING_NUL)));

sv = newSV(0);
sv_usepvn_flags(sv, ptr, len, flags & SV_HAS_TRAILING_NUL);
if ((flags & SVf_UTF8) && SvOK(sv)) {
SvUTF8_on(sv);
}

SvTAINT(sv);

if (flags & SVs_TEMP) {
sv_2mortal(sv);
}

return sv;
}

注: ptr应该指向 Newx 分配的内存,并且它必须指向 Newx 返回的 block 的开头.

注意:接受标志 SVf_UTF8 (指定 ptr 是要在 Perl 中看到的字符串的 UTF-8 编码), SVs_TEMP (在 SV 上调用 sv_2mortal)和 SV_HAS_TRAILING_NUL (见下文)。

注意:一些代码期望标量的字符串缓冲区有一个尾随 NUL(即使缓冲区的长度已知并且即使缓冲区可以包含 NUL)。如果您分配的内存块在数据末尾有一个尾随 NUL(例如 C 风格的 NUL 终止字符串),则传递 SV_HAS_TRAILING_NUL旗帜。如果不是,该函数将尝试扩展缓冲区并添加 NUL。

关于Perl SV 值来自没有副本的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30762901/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com