根据perlapi,sv_catpv()
的工作原理如下:
将以
NUL
结尾的字符串连接到SV中的字符串末尾。如果SV设置了UTF-8状态,则附加的字节应为有效的UTF-8。处理"获取"魔法,但不处理"设置"魔法。
void sv_catpv(SV *const sv, const char* ptr)
不过,我发现的大多数XS教程都使用sv_catpvs()
,它可以做到这一点:
与
sv_catpvn
类似,但采用文字字符串而不是字符串/长度对。
void sv_catpvs(SV* sv, const char* s)
好吧,这不是很有帮助,所以让我们看看sv_catpvn()
:
将字符串连接到SV中的字符串末尾。
len
表示要复制的字节数。如果SV设置了UTF-8状态,那么附加的字节应该是有效的UTF-8。处理"获取"魔法,但不处理"设置"魔法。
void sv_catpvn(SV *dsv, const char *sstr, STRLEN len)
因此,sv_catpvn
与sv_catpv
的作用相同,只是它将字符串长度作为一个单独的参数,而sv_catpvs
与sv_catpvn
的作用相同。
sv_catpv
和sv_catpvs
之间有没有我遗漏的细微区别,或者它们只是做同一件事的两种方式?
根据您引用的段落,sv_catpvs
只接受字符串文字。
const char *str = "foo";
sv_catpvs(sv, "foo"); // ok
sv_catpvs(sv, str); // ERROR
另一方面,sv_catpv
接受任何返回字符串的表达式。
sv_catpv(sv, "foo"); // ok
sv_catpv(sv, str); // ok
那么sv_catpvs
为什么存在呢?因为它更快。sv_catpvs
之所以只接受字符串文字,是因为它是一个扩展的宏
sv_catpvs(sv, "foo")
变成类似的东西
sv_catpvn_flags(sv, "foo", sizeof("foo")-1, SV_GMAGIC)
其解析为
sv_catpvn_flags(sv, "foo", 3, SV_GMAGIC)
在编译时。另一方面,sv_catpv
被迫使用较慢的strlen
。