Perl XS:创建并 return 字符串数组 (char*) 取自调用 C 函数或失败时的 undef
Perl XS: create and return array of strings (char*) taken from calling a C function or undef on failure
我有 Perl XS 代码,它从外部 C 库调用一个函数 returns char **
(字符串数组)。
XS 代码最终将 return 返回给 Perl 一个包含所有字符串结果的数组引用。或 undef
失败。
我有两个问题:
- 程序退出时,我得到一个核心转储,其中包含有关内存损坏、双重释放等消息(例如
double free or corruption (fasttop)
)。
- 如何 return 来自 XS sub 的 undef 值表示出现问题(不是空数组)?
此外,如果有人可以确认我正在正确处理从 Perl 到 C 函数的字符串是 utf8 编码的情况(例如输入文件名)或从 C 函数返回的结果(可能包含 utf8 字符串) ) 被发送回 Perl OK。
这是我的代码(根据 建模,如果我没看错,示例 #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. (e.g. double free or corruption (fasttop)).
这可能是因为您覆盖了 for
中的循环变量 results_sz
导致了未定义的行为。
How to return an undef value from XS sub denoting that something went wrong (not an empty array)?
您可以 return &PL_sv_undef
表示未定义的值,请参阅 perlxs 了解更多信息。例如像这样:
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 (e.g. the input filename)
要将 Perl UTF-8 字符串作为 UTF-8 编码字符串传递给 C-function,您可以使用 SvPVutf8()
而不是 SvPVbyte()
,请参阅 perlguts想要查询更多的信息。示例:
infilename = SvPVutf8(infilename_SV, infilename_len);
or the results back from the C function (which may contain utf8 strings) are sent back to Perl
您可以使用 newSVpvn_flags()
而不是 newSVpvn()
将 UTF-8 编码的 C-string 转换为 Perl 字符串。例如:
aresult = newSVpvn_flags(results[I], strlen(results[I]), SVf_UTF8);
我有 Perl XS 代码,它从外部 C 库调用一个函数 returns char **
(字符串数组)。
XS 代码最终将 return 返回给 Perl 一个包含所有字符串结果的数组引用。或 undef
失败。
我有两个问题:
- 程序退出时,我得到一个核心转储,其中包含有关内存损坏、双重释放等消息(例如
double free or corruption (fasttop)
)。 - 如何 return 来自 XS sub 的 undef 值表示出现问题(不是空数组)?
此外,如果有人可以确认我正在正确处理从 Perl 到 C 函数的字符串是 utf8 编码的情况(例如输入文件名)或从 C 函数返回的结果(可能包含 utf8 字符串) ) 被发送回 Perl OK。
这是我的代码(根据
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. (e.g. double free or corruption (fasttop)).
这可能是因为您覆盖了 for
中的循环变量 results_sz
导致了未定义的行为。
How to return an undef value from XS sub denoting that something went wrong (not an empty array)?
您可以 return &PL_sv_undef
表示未定义的值,请参阅 perlxs 了解更多信息。例如像这样:
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 (e.g. the input filename)
要将 Perl UTF-8 字符串作为 UTF-8 编码字符串传递给 C-function,您可以使用 SvPVutf8()
而不是 SvPVbyte()
,请参阅 perlguts想要查询更多的信息。示例:
infilename = SvPVutf8(infilename_SV, infilename_len);
or the results back from the C function (which may contain utf8 strings) are sent back to Perl
您可以使用 newSVpvn_flags()
而不是 newSVpvn()
将 UTF-8 编码的 C-string 转换为 Perl 字符串。例如:
aresult = newSVpvn_flags(results[I], strlen(results[I]), SVf_UTF8);