2016-06-04 4 views
2

J'ai un fichier SWIG pour faire beaucoup de liaisons pour les langues. Il y a une variable dans la source C, qui est une liste de longueur fixe, avec un type entier. Quand j'y accède en Perl, il n'y a pas d'éléments - montre simplement que c'est un ARRAY.SWIG typedef - Perl array

Même problème était en Python, mais je ne pouvais fixe avec un typemap SWIG:

#ifdef SWIGPYTHON 
%typemap(out) int [ANY] { 
    ... 

Ok, I'ld aiment à le faire à nouveau avec Perl - mais je ne suis pas un expert en Perl, Je peux corriger ce typemap pour Perl. Voilà ce que je cherche:

#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", $1_dim0); 
    len = $1_dim0; 

    for (i = 0; i < len ; i++) { 
     SV* perlval = newSV(0); 
     sv_setiv(perlval, (IV)$1[i]); 
     av_push(av, perlval); 
    } 
    SvSetSV($result, newRV_noinc((SV *)av)); 
} 
#endif 

Le script Perl me montre le "len: 10", quand il fonctionne, mais le tableau est vide:

$i=1; 
foreach(@m) { 
    print $i, "'", $_, "'\n"; 
    $i=$i+1; 
} 

le résultat est:

0 ''

Qu'est-ce qui me manque?

Merci,

a.

EDIT: voici le script 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; 
} 

Maintenant, ce script produit ce résultat:

len: 10 
0'' 

Le "len: 10" sortie est venu de SWIG typedef - voir "printf (" len:% d ... "line ...

+0

J'ai terminé la post - voir la partie "EDIT". De quoi avez-vous besoin encore plus? – airween

+0

[Croisé] (http: //www.perlmonks.org /? node_id = 1164929). – choroba

+0

Oui, c'est crossposted - y a-t-il une liste de forums/listes de diffusion, cela dépend de Stackoverflow, et sera marqué comme crosspost? Je pensais que le SO et Perlmonks sont deux endroits différents. En tout cas, je m'excuse pour crosspost, désolé. – airween

Répondre

1

Je n'ai jamais utilisé SWIG auparavant, mais je pensais que ça pourrait être intéressant d'en apprendre un peu plus à ce sujet. fou Quelque chose qui pourrait résoudre votre problème. Tout d'abord nous avons besoin du fichier d'interface example.i:

%module example 

%typemap(out) int [ANY] { 
    AV* av = newAV(); 
    int i = 0,len = 0; 
    len = $1_dim0; 

    for (i = 0; i < len ; i++) { 
     SV* perlval = newSV(0); 
     sv_setiv(perlval, (IV)$1[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); 
    $1 = (int *) malloc((len+1)*sizeof(int)); 
    for (i = 0; i <= len; i++) { 
    tv = av_fetch(tempav, i, 0); 
    $1[i] = (int) SvIV(*tv); 
    } 
} 

%typemap(freearg) int * { 
    free($1); 
} 

%typemap(memberin) int [ANY] { 
    int i; 
    for (i = 0; i < $1_dim0; i++) { 
     $1[i] = $input[i]; 
    } 
} 

%inline %{ 

struct m { 
    int ilist[3]; 
}; 

%} 

Ensuite, nous avons besoin de créer un script Perl pour tester le package 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; 
} 

La sortie est maintenant (après la compilation du fichier d'interface et l'exécution du Perl script):

0: '1' 
1: '2' 
2: '3' 

Remarque:

  • j'ai installé SWIG 3.0.8 (sur Ubuntu 16.04) en utilisant

    $ sudo apt-get install swig 
    
  • Je compilé le fichier d'interface à l'aide 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 
    
+1

Salut Håkon, merci beaucoup pour votre aide. On dirait que mon fichier SWIG, typemaps et tous les composants sauf le fichier Perl ont raison. Je ne suis pas un gourou Perl (je ne connais vraiment pas Perl), j'ai juste foiré le devoir et la marche du tableau - voir le script Perl ici: http://www.perlmonks.org/?node_id=1164929. Merci beaucoup encore! – airween