如何从c++;在perl中转换为哈希 我是新来的Sigg,我正在尝试将C++映射转换成Perl中的哈希。 有一个Perl扩展,使用C++需要将多维数组或映射返回到Perl。 我在swig接口文件中使用了该模板,但它给出了空结果

如何从c++;在perl中转换为哈希 我是新来的Sigg,我正在尝试将C++映射转换成Perl中的哈希。 有一个Perl扩展,使用C++需要将多维数组或映射返回到Perl。 我在swig接口文件中使用了该模板,但它给出了空结果,c++,perl,swig,C++,Perl,Swig,swig接口文件: %include "exception.i" %exception { try { $action } catch (const std::exception &e) { SWIG_exception_fail(SWIG_RuntimeError, e.what()); } } %module new_tr %{ /* Put headers and other declaratio

swig接口文件:

%include "exception.i"
%exception {

    try {
        $action
        } catch (const std::exception &e) {

        SWIG_exception_fail(SWIG_RuntimeError, e.what());
        }
    }

%module new_tr
%{
/* Put headers and other declarations here */
#include "new_tr.h"
%}
%include <std_map.i>

%template(StringStringMap) std::map<int,  std::map<std::string,std::string>>;

%include "new_tr.h"
     std::map<int,  std::map<std::string,std::string>> Memberfunction::m;
    std::map<int,  std::map<std::string,std::string>> Memberfunction::getResult()
    {
        return m;
    }
电流输出:

$VAR1 = bless( {}, 'new_tr::StringStringMap' );
预期输出:(多维散列)


下面是一个示例,说明如何将
%typemap
用于嵌套的
std::map

新的\u tr.i

%module new_tr
%typemap(out) std::map<int, std::map<std::string,std::string>> {
    HV *hash = (HV *) newHV();
    for (auto const& item : $1) {
        HV *subhash;
        char *keysv;
        auto map = item.second;
        subhash = (HV *) newHV();
        for (auto const &item2 : map) {
            SV *sv;
            auto key2 = item2.first.c_str();
            auto value = item2.second.c_str();
            sv = newSVpvn( value, strlen(value) );
            hv_store (subhash, key2, strlen(key2), sv, 0);
        }
        auto key = std::to_string(item.first).c_str();
        hv_store (hash, key, strlen(key), (SV*) newRV_noinc((SV*)subhash), 0);
    }  
    $result = newRV_noinc((SV*) hash);
    sv_2mortal($result);
    argvi++;
} 
%{
#include "new_tr.h"
%}
%include "new_tr.h"
#include <map>
#include <string>
using ssmap = std::map<int,  std::map<std::string,std::string>>;
ssmap getResult();
#include "new_tr.h"

ssmap getResult()
{
    ssmap map = {
        {1, {{"Brown","Manager"}, {"Smith", "Salesman"}, {"Albert", "Salesman"}}},
        {2, {{"Penfold", "Designer"}, {"Evans", "Tea-person"}, {"Jurgens", "Manager"}}}
    };

    return map;
}
use strict;
use warnings;
use Data::Dumper;
use lib '.';
use new_tr;

my $map = new_tr::getResult();
print Dumper( $map );
$VAR1 = {
          '1' => {
                   'Albert' => 'Salesman',
                   'Smith' => 'Salesman',
                   'Brown' => 'Manager'
                 },
          '2' => {
                   'Penfold' => 'Designer',
                   'Jurgens' => 'Manager',
                   'Evans' => 'Tea-person'
                 }
        };
然后使用以下命令编译模块:

perl_include_dir=$(perl -MConfig -e'print $Config{archlib}')"/CORE"
swig -perl5 -c++ -I/usr/include new_tr.i 
g++ -fPIC -c new_tr.cxx
g++ -I${perl_include_dir} -c -fPIC -g -o new_tr_wrap.o new_tr_wrap.cxx
g++ -shared -L. new_tr.o new_tr_wrap.o -o new_tr.so
然后用test.pl测试它:

%module new_tr
%typemap(out) std::map<int, std::map<std::string,std::string>> {
    HV *hash = (HV *) newHV();
    for (auto const& item : $1) {
        HV *subhash;
        char *keysv;
        auto map = item.second;
        subhash = (HV *) newHV();
        for (auto const &item2 : map) {
            SV *sv;
            auto key2 = item2.first.c_str();
            auto value = item2.second.c_str();
            sv = newSVpvn( value, strlen(value) );
            hv_store (subhash, key2, strlen(key2), sv, 0);
        }
        auto key = std::to_string(item.first).c_str();
        hv_store (hash, key, strlen(key), (SV*) newRV_noinc((SV*)subhash), 0);
    }  
    $result = newRV_noinc((SV*) hash);
    sv_2mortal($result);
    argvi++;
} 
%{
#include "new_tr.h"
%}
%include "new_tr.h"
#include <map>
#include <string>
using ssmap = std::map<int,  std::map<std::string,std::string>>;
ssmap getResult();
#include "new_tr.h"

ssmap getResult()
{
    ssmap map = {
        {1, {{"Brown","Manager"}, {"Smith", "Salesman"}, {"Albert", "Salesman"}}},
        {2, {{"Penfold", "Designer"}, {"Evans", "Tea-person"}, {"Jurgens", "Manager"}}}
    };

    return map;
}
use strict;
use warnings;
use Data::Dumper;
use lib '.';
use new_tr;

my $map = new_tr::getResult();
print Dumper( $map );
$VAR1 = {
          '1' => {
                   'Albert' => 'Salesman',
                   'Smith' => 'Salesman',
                   'Brown' => 'Manager'
                 },
          '2' => {
                   'Penfold' => 'Designer',
                   'Jurgens' => 'Manager',
                   'Evans' => 'Tea-person'
                 }
        };
输出

%module new_tr
%typemap(out) std::map<int, std::map<std::string,std::string>> {
    HV *hash = (HV *) newHV();
    for (auto const& item : $1) {
        HV *subhash;
        char *keysv;
        auto map = item.second;
        subhash = (HV *) newHV();
        for (auto const &item2 : map) {
            SV *sv;
            auto key2 = item2.first.c_str();
            auto value = item2.second.c_str();
            sv = newSVpvn( value, strlen(value) );
            hv_store (subhash, key2, strlen(key2), sv, 0);
        }
        auto key = std::to_string(item.first).c_str();
        hv_store (hash, key, strlen(key), (SV*) newRV_noinc((SV*)subhash), 0);
    }  
    $result = newRV_noinc((SV*) hash);
    sv_2mortal($result);
    argvi++;
} 
%{
#include "new_tr.h"
%}
%include "new_tr.h"
#include <map>
#include <string>
using ssmap = std::map<int,  std::map<std::string,std::string>>;
ssmap getResult();
#include "new_tr.h"

ssmap getResult()
{
    ssmap map = {
        {1, {{"Brown","Manager"}, {"Smith", "Salesman"}, {"Albert", "Salesman"}}},
        {2, {{"Penfold", "Designer"}, {"Evans", "Tea-person"}, {"Jurgens", "Manager"}}}
    };

    return map;
}
use strict;
use warnings;
use Data::Dumper;
use lib '.';
use new_tr;

my $map = new_tr::getResult();
print Dumper( $map );
$VAR1 = {
          '1' => {
                   'Albert' => 'Salesman',
                   'Smith' => 'Salesman',
                   'Brown' => 'Manager'
                 },
          '2' => {
                   'Penfold' => 'Designer',
                   'Jurgens' => 'Manager',
                   'Evans' => 'Tea-person'
                 }
        };

cpp
文件中,什么是
数据库
Database::getResult
不应该是
new\u tr::getResult
?同样在
cpp
文件中,您返回
m
,但是
m
没有定义。我认为您需要为映射创建一个输出
typemap
,例如
%typemap(out)std::map{…}
@Håkonh230;感谢您的回复,数据库是类的成员函数,m是映射。我已经编辑了这个问题,请检查一下now@HåkonHægland感谢您的回复,我如何在swig中使用typemap将3d map转换为哈希。您的预期输出显示一个
映射,但您的代码定义了一个
映射,这是一个打字错误吗?@VinothRaja修复了typemap中的一个错误,请参阅我的更新答案。返回的散列的引用计数不应该增加,因为引用是致命的,并且在C++代码中不再需要。