Perl Swig におけるSTLのvector/string typemap

Google Cacheからお宝発見。http://72.14.207.104/search?q=cache:-HxRbJf6tigJ:mailman.cs.uchicago.edu/pipermail/swig/2002-August/005367.html+typemap+perl+swig+array+char&hl=ja&gl=jp&ct=clnk&cd=4
PerlSwigC++STL(vector, string)のtypemap。

追記:
Perl側から arrayリファレンスを渡して、vector* でうけとるのはできた。
同じく、vectorをreturnして、arrayリファレンスで受け取るのもできた。ヽ(´ー`)ノ
ただし vector_tempがないとか言われるので適当にごにょる。
スマートな解決方法をご存知の方ぜひつっこみをお願いします。


いつなくなるか分からないので全文引用しておきます。

Chris Seatory  chriss@regasia.com
Mon, 5 Aug 2002 13:35:21 +1000

    * Previous message: [Swig] Inserting #includes before the rest of the wrapper code (again)
    * Next message: [Swig] C++ / Perl STL mappings
    * Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

Hi,

After a few recent clues from David Beasley and Brett H. Williams,
I've now fixed all memory leaks in my Perl 5 <-> C++ mappings.

Below, you will find my typemaps for:
  perl5 string <-> c++ std::string
  perl5 string <-> c++ std::string pointer or reference
  perl5 array ref <-> c++ std::vector<std::string>
  perl5 array ref <-> c++ std::vector<std::string> pointer or reference
  perl5 array ref <-> c++ std::vector<OBJECT>
  perl5 array ref <-> c++ std::vector<OBJECT> pointer or reference

Simply copy the code below into "perl5-stl.i", and %include it in your
interface file. To add support for each vector, in your interface file
specify:
  VECTORIN(MyObject)
  VECTOROUT(MyObject)

I am keen to contribute to SWIG's C++ STL support for Perl. If you'd
like my help, please let me know where to start.


Cheers,
Chris Seatory
Programmer
AusRegistry Pty Ltd
Melbourne, Australia


/*
   SWIG PERL5/C++ typemaps for C++ STL strings and vectors
     refer to "perlguts" man page and SWIG manual
   Author: Chris Seatory <chriss@regasia.com>
   Version: $Id: perl5-stl.i,v 1.2 2002/08/05 03:12:42 chriss Exp $
*/

/* INPUT ARGUMENT TYPE MAPPINGS */

// Perl5 string
// C++ pointer or reference to STL string
%typemap(in) std::string*, std::string& ($basetype string_temp) {
  if (!SvPOK($input))
    croak("Argument $argnum is not a string");
  STRLEN len;
  char *ptr = SvPV($input, len);
  string_temp.assign(ptr, len);
  $1 = &string_temp;
  argvi++;
}
// Perl5 string
// C++ STL string
%typemap(in) std::string {
  if (!SvPOK($input))
    croak("Argument $argnum is not a string");
  STRLEN len;
  char *ptr = SvPV($input, len);
  $1 = std::string(ptr, len);
  argvi++;
}


// Perl5 reference to array of strings
// C++ pointer or reference to STL vector of STL strings
%typemap(in) std::vector<std::string>*, std::vector<std::string>&
($basetype vec
tor_temp) {
  if (!SvROK($input))
    croak("$input is not a reference.");
  AV *av = (AV *)SvRV($input);
  if (SvTYPE(av) != SVt_PVAV)
    croak("$input is not an array.");

  SV **tv;
  I32 l = av_len(av) + 1;

  STRLEN len;
  for (int i = 0; i < l; i++) {
    tv = av_fetch(av, i, 0);
    std::string str = std::string(SvPV(*tv, len));
    vector_temp.push_back(str);
  }
  $1 = &vector_temp;
  argvi++;
}


%define VECTORIN(OBJECT)
// Perl5 reference to array of arbitrary objects
// C++ pointer or reference to STL vector of objects
%typemap(in) std::vector<OBJECT>*, std::vector<OBJECT>& ($basetype
vector_temp)
{
  if (!SvROK($input))
    croak("$input is not a reference.");
  AV *av = (AV *)SvRV($input);
  if (SvTYPE(av) != SVt_PVAV)
    croak("$input is not an array.");

  SV **tv;
  I32 len = av_len(av) + 1;
  OBJECT *obj;
  swig_type_info *ti = SWIG_TypeQuery("OBJECT");
  int i;
  for (i = 0; i < len; i++) {
    tv = av_fetch(av, i, 0);
    SWIG_ConvertPtr(*tv, (void **)&obj, ti, 0);
    vector_temp.push_back(*obj);
  }
  $1 = &vector_temp;
  argvi++;
}
%enddef


/* OUTPUT ARGUMENT TYPE MAPPINGS */

// C++ pointer or reference to STL string
// Perl5 string
%typemap(out) std::string*, std::string& {
  $result = sv_newmortal();
  sv_setpvn($result, ($1)->data(), ($1)->size());
  argvi++;
}
// C++ STL string
// Perl5 string
%typemap(out) std::string {
  $result = sv_newmortal();
  sv_setpvn($result, ($1).data(), ($1).size());
  argvi++;
}


// C++ pointer or reference to STL vector of STL strings
// Perl5 reference to array of strings
%typemap(out) std::vector<std::string>*, std::vector<std::string>& {
  int len = ($1)->size();
  SV **svs = new SV*[len];
  for (int x = 0; x < len; x++) {
    SV* sv = sv_newmortal();
    sv_setpvn(sv, $1->at(x).data(), $1->at(x).size());
    svs[x] = sv;
  }
  AV *myav = av_make(len, svs);
  delete[] svs;
  $result = newRV_noinc((SV*) myav);
  sv_2mortal($result);
  argvi++;
}
// C++ STL vector of STL strings
// Perl5 reference to array of strings
%typemap(out) std::vector<std::string> {
  int len = $1.size();
  SV **svs = new SV*[len];
  for (int x = 0; x < len; x++) {
    SV* sv = sv_newmortal();
    sv_setpvn(sv, $1[x].data(), $1[x].size());
    svs[x] = sv;
  }
  AV *myav = av_make(len, svs);
  delete[] svs;
  $result = newRV_noinc((SV*) myav);
  sv_2mortal($result);
  argvi++;
}


%define VECTOROUT(OBJECT)
// C++ pointer or reference to STL vector of arbitrary objects
// Perl5 reference to array of arbitrary objects
%typemap(out) std::vector<OBJECT>*, std::vector<OBJECT>& {
  int len = $1->size();
  SV **svs = new SV*[len];
  for (int x = 0; x < len; x++) {
    svs[x] = sv_newmortal();
    SWIG_MakePtr(svs[x], (void*)&($1->at(x)), SWIGTYPE_p_ ## OBJECT, 0);
  }
  AV *myav = av_make(len, svs);
  delete[] svs;
  $result = newRV_noinc((SV*) myav);
  sv_2mortal($result);
  argvi++;
}
// C++ STL vector of arbitrary objects
// Perl5 reference to array of arbitrary objects
%typemap(out) std::vector<OBJECT> {
  int len = $1.size();
  SV **svs = new SV*[len];
  for (int x = 0; x < len; x++) {
    svs[x] = sv_newmortal();
    SWIG_MakePtr(svs[x], (void*)&($1[x]), SWIGTYPE_p_ ## OBJECT, 0);
  }
  AV *myav = av_make(len, svs);
  delete[] svs;
  $result = newRV_noinc((SV*) myav);
  sv_2mortal($result);
  argvi++;
}
%enddef