SWIG typedef - Perl 数组
SWIG typedef - Perl array
我有一个 SWIG 文件可以为多种语言进行绑定。 C源代码中有一个变量,它是一个定长列表,整数类型。当我在 Perl 中访问它时,它没有任何项目 - 只显示它是一个数组。
同样的问题出现在 Python 中,但我可以使用 SWIG typemap 修复它:
#ifdef SWIGPYTHON
%typemap(out) int [ANY] {
...
好的,我想用 Perl 再做一次 - 但我不是 Perl 专家,所以我可以为 Perl 修复这个类型映射。这是我尝试的:
#ifdef SWIGPERL
%typemap(out) int [ANY] {
SV* sv = newSV(0);
AV* av = (AV *)sv_2mortal((SV *)newAV());
int i = 0,len = 0;
printf("len: %d\n", _dim0);
len = _dim0;
for (i = 0; i < len ; i++) {
SV* perlval = newSV(0);
sv_setiv(perlval, (IV)[i]);
av_push(av, perlval);
}
SvSetSV($result, newRV_noinc((SV *)av));
}
#endif
perl 脚本在运行时显示 "len: 10",但数组为空:
$i=1;
foreach(@m) {
print $i, "'", $_, "'\n";
$i=$i+1;
}
结果是:
0''
我错过了什么?
谢谢,
一个.
编辑:这是 Perl 脚本:
#!/usr/bin/perl
use example1;
# this function set up the built-in list in example1 module
example1::get_att(7);
my @m = $example1::m->{ilist};
# "m" is a C structure in C source, and it has an "int ilist[10];" member.
# get_att(int n) will fill this list with "n" number
# This will be accesable in binded lanugage (eg in Python) as like this:
# print m.ilist -> [0, 3, 6, 9, 12, 15, 18, 0, 0, 0]
$i = 0;
foreach(@m) {
print $i, "'", $_, "'\n";
$i=$i+1;
}
现在,这个脚本产生这个结果:
len: 10
0''
"len: 10" 输出来自 SWIG typedef - 请参阅 "printf("len: %d...”行...
我以前没有使用过 SWIG,但我认为了解一下它可能会很有趣。在阅读 documentation 几个小时后,我想我可能找到了可以解决您的问题的东西。首先我们需要接口文件 example.i
:
%module example
%typemap(out) int [ANY] {
AV* av = newAV();
int i = 0,len = 0;
len = _dim0;
for (i = 0; i < len ; i++) {
SV* perlval = newSV(0);
sv_setiv(perlval, (IV)[i]);
av_push(av, perlval);
}
$result = newRV_noinc((SV*) av );
sv_2mortal( $result );
argvi++;
}
%typemap(in) int [ANY] {
AV *tempav;
I32 len;
int i;
SV **tv;
if (!SvROK($input))
croak("Argument $argnum is not a reference.");
if (SvTYPE(SvRV($input)) != SVt_PVAV)
croak("Argument $argnum is not an array.");
tempav = (AV*)SvRV($input);
len = av_len(tempav);
= (int *) malloc((len+1)*sizeof(int));
for (i = 0; i <= len; i++) {
tv = av_fetch(tempav, i, 0);
[i] = (int) SvIV(*tv);
}
}
%typemap(freearg) int * {
free();
}
%typemap(memberin) int [ANY] {
int i;
for (i = 0; i < _dim0; i++) {
[i] = $input[i];
}
}
%inline %{
struct m {
int ilist[3];
};
%}
然后我们需要创建一个 Perl 脚本来测试 example::m
包:
use feature qw(say);
use strict;
use warnings;
use example;
my $m = example::m->new();
$m->{ilist} = [1, 2, 3];
my $list = $m->{ilist};
my $i = 0;
for ( @$list ) {
say "$i: '$_'";
$i=$i+1;
}
现在的输出是(在编译接口文件和 运行 Perl 脚本之后):
0: '1'
1: '2'
2: '3'
注:
我首先使用
安装了 SWIG 3.0.8(在 Ubuntu 16.04 上)
$ sudo apt-get install swig
然后我编译接口文件example.i
使用:
$ swig -perl5 example.i
$ gcc -fpic -c -Dbool=char -D_GNU_SOURCE \
-I/usr/lib/x86_64-linux-gnu/perl/5.22/CORE example_wrap.c
$ gcc -shared example.o example_wrap.o -o example.so
我有一个 SWIG 文件可以为多种语言进行绑定。 C源代码中有一个变量,它是一个定长列表,整数类型。当我在 Perl 中访问它时,它没有任何项目 - 只显示它是一个数组。
同样的问题出现在 Python 中,但我可以使用 SWIG typemap 修复它:
#ifdef SWIGPYTHON
%typemap(out) int [ANY] {
...
好的,我想用 Perl 再做一次 - 但我不是 Perl 专家,所以我可以为 Perl 修复这个类型映射。这是我尝试的:
#ifdef SWIGPERL
%typemap(out) int [ANY] {
SV* sv = newSV(0);
AV* av = (AV *)sv_2mortal((SV *)newAV());
int i = 0,len = 0;
printf("len: %d\n", _dim0);
len = _dim0;
for (i = 0; i < len ; i++) {
SV* perlval = newSV(0);
sv_setiv(perlval, (IV)[i]);
av_push(av, perlval);
}
SvSetSV($result, newRV_noinc((SV *)av));
}
#endif
perl 脚本在运行时显示 "len: 10",但数组为空:
$i=1;
foreach(@m) {
print $i, "'", $_, "'\n";
$i=$i+1;
}
结果是:
0''
我错过了什么?
谢谢,
一个.
编辑:这是 Perl 脚本:
#!/usr/bin/perl
use example1;
# this function set up the built-in list in example1 module
example1::get_att(7);
my @m = $example1::m->{ilist};
# "m" is a C structure in C source, and it has an "int ilist[10];" member.
# get_att(int n) will fill this list with "n" number
# This will be accesable in binded lanugage (eg in Python) as like this:
# print m.ilist -> [0, 3, 6, 9, 12, 15, 18, 0, 0, 0]
$i = 0;
foreach(@m) {
print $i, "'", $_, "'\n";
$i=$i+1;
}
现在,这个脚本产生这个结果:
len: 10
0''
"len: 10" 输出来自 SWIG typedef - 请参阅 "printf("len: %d...”行...
我以前没有使用过 SWIG,但我认为了解一下它可能会很有趣。在阅读 documentation 几个小时后,我想我可能找到了可以解决您的问题的东西。首先我们需要接口文件 example.i
:
%module example
%typemap(out) int [ANY] {
AV* av = newAV();
int i = 0,len = 0;
len = _dim0;
for (i = 0; i < len ; i++) {
SV* perlval = newSV(0);
sv_setiv(perlval, (IV)[i]);
av_push(av, perlval);
}
$result = newRV_noinc((SV*) av );
sv_2mortal( $result );
argvi++;
}
%typemap(in) int [ANY] {
AV *tempav;
I32 len;
int i;
SV **tv;
if (!SvROK($input))
croak("Argument $argnum is not a reference.");
if (SvTYPE(SvRV($input)) != SVt_PVAV)
croak("Argument $argnum is not an array.");
tempav = (AV*)SvRV($input);
len = av_len(tempav);
= (int *) malloc((len+1)*sizeof(int));
for (i = 0; i <= len; i++) {
tv = av_fetch(tempav, i, 0);
[i] = (int) SvIV(*tv);
}
}
%typemap(freearg) int * {
free();
}
%typemap(memberin) int [ANY] {
int i;
for (i = 0; i < _dim0; i++) {
[i] = $input[i];
}
}
%inline %{
struct m {
int ilist[3];
};
%}
然后我们需要创建一个 Perl 脚本来测试 example::m
包:
use feature qw(say);
use strict;
use warnings;
use example;
my $m = example::m->new();
$m->{ilist} = [1, 2, 3];
my $list = $m->{ilist};
my $i = 0;
for ( @$list ) {
say "$i: '$_'";
$i=$i+1;
}
现在的输出是(在编译接口文件和 运行 Perl 脚本之后):
0: '1'
1: '2'
2: '3'
注:
我首先使用
安装了 SWIG 3.0.8(在 Ubuntu 16.04 上)$ sudo apt-get install swig
然后我编译接口文件
example.i
使用:$ swig -perl5 example.i $ gcc -fpic -c -Dbool=char -D_GNU_SOURCE \ -I/usr/lib/x86_64-linux-gnu/perl/5.22/CORE example_wrap.c $ gcc -shared example.o example_wrap.o -o example.so