[英]Perl XS: create and return array of strings (char*) taken from calling a C function or undef on failure
I have Perl XS code which calls a function from an external C library which returns char **
(array of strings).我有 Perl XS 代码,它从返回char **
(字符串数组)的外部 C 库调用 function。
The XS code will eventually return back to Perl an array ref with all the string results in there. XS 代码最终将返回 Perl 一个数组引用,其中包含所有字符串结果。 Or undef
on failure.或者undef
失败。
I have 2 problems:我有两个问题:
double free or corruption (fasttop)
).在程序退出时,我得到一个核心转储,其中包含有关 memory 损坏、双重释放等的消息(例如double free or corruption (fasttop)
)。Additionally, if anyone can confirm that I am handling correctly the cases where strings from Perl into the C function are utf8-encoded (eg the input filename) or the results back from the C function (which may contain utf8 strings) are sent back to Perl OK.此外,如果有人可以确认我正在正确处理以下情况:从 Perl 到 C function 的字符串是 utf8 编码的(例如输入文件名)或从 C function 返回的结果(可能包含 utf8 字符串)被发送回Perl 好的。
Here's my code (which is modelled after https://stackoverflow.com/a/46719397/385390 If I got that correctly, example #1):这是我的代码(以https://stackoverflow.com/a/46719397/385390为蓝本,如果我理解正确,示例 #1):
AV *
decode(infilename_SV)
SV *infilename_SV
PREINIT:
char *infilename;
STRLEN infilename_len;
char **results;
size_t results_sz;
char *aresult;
size_t I;
SV **aresultPP;
char *dummy;
STRLEN dummy_len;
CODE:
infilename = SvPVbyte(infilename_SV, infilename_len)
// call C function
results = myfunc(infilename, &results_sz);
if( results == NULL ){
printf("error!");
// HOW TO return undef (and not an empty array?)
}
// create a Perl array to be returned
RETVAL = (AV*)sv_2mortal((SV*)newAV());
for(I=0;I<results_sz;I++){
results_sz = strlen(results[I]);
// create a new Perl string and copy this result
aresult = newSVpv(results[I], 0);
av_push(RETVAL, aresult);
// free results as returned by C call
free(results[I]);
}
// free results as returned by C call
free(results);
// debug print results
for(I=0;I<results_sz;I++){
aresultPP = av_fetch((AV *)RETVAL, I, 0);
dummy = SvPVbyte(*apayloadPP, dummy_len);
printf("result: %s\n", dummy);
}
OUTPUT:
RETVAL
On program exit I get a core dump with messages about memory corruption, double free etc. (eg double free or corruption (fasttop)).在程序退出时,我得到一个核心转储,其中包含有关 memory 损坏、双重释放等的消息(例如双重释放或损坏 (fasttop))。
This was probably because you overwrote the loop variable results_sz
inside the for
causing undefined behavior.这可能是因为您覆盖了for
中的循环变量results_sz
导致未定义的行为。
How to return an undef value from XS sub denoting that something went wrong (not an empty array)?如何从 XS sub 返回一个 undef 值,表示出现问题(不是空数组)?
You can return &PL_sv_undef
to signal an undefined value, see perlxs for more information.您可以返回&PL_sv_undef
以表示未定义的值,有关更多信息,请参阅perlxs 。 For example like this:例如像这样:
SV *
decode(infilename_SV)
SV *infilename_SV
PREINIT:
char *infilename;
STRLEN infilename_len;
char **results;
size_t results_sz;
char *aresult;
size_t I;
CODE:
infilename = SvPVbyte(infilename_SV, infilename_len);
results = myfunc(infilename, &results_sz);
if( results == NULL ){
RETVAL = &PL_sv_undef;
}
else {
AV *av = newAV();
for(I=0; I < results_sz; I++){
aresult = newSVpv(results[I], 0);
av_push(av, aresult);
free(results[I]);
}
free(results);
RETVAL = sv_2mortal(newRV_noinc((SV*)av));
}
OUTPUT:
RETVAL
if anyone can confirm that I am handling correctly the cases where strings from Perl into the C function are utf8-encoded (eg the input filename)如果有人可以确认我正在正确处理从 Perl 到 C function 的字符串是 utf8 编码的情况(例如输入文件名)
To pass a Perl UTF-8 string to the C-function as an UTF-8 encoded character string you can use SvPVutf8()
instead of SvPVbyte()
, see perlguts for more information.要将 Perl UTF-8 字符串作为 UTF-8 编码字符串传递给 C 函数,您可以使用SvPVutf8()
而不是SvPVbyte()
,请参阅perlguts了解更多信息。 Example:例子:
infilename = SvPVutf8(infilename_SV, infilename_len);
or the results back from the C function (which may contain utf8 strings) are sent back to Perl或者将 C function 返回的结果(可能包含 utf8 字符串)发送回 Perl
You can use newSVpvn_flags()
instead of newSVpvn()
to convert an UTF-8 encoded C-string to a Perl string.您可以使用newSVpvn_flags()
而不是newSVpvn()
将 UTF-8 编码的 C 字符串转换为 Perl 字符串。 For example:例如:
aresult = newSVpvn_flags(results[I], strlen(results[I]), SVf_UTF8);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.