c++ - 如何将多维映射从 c++ 转换为 perl 中的哈希

标签 c++ perl swig

我是 swig 的新手,我正在尝试将 c++ 映射转换为 Perl 中的哈希。

有一个使用 c++ 的 Perl 扩展需要返回一个多维数组或映射到 Perl。
我在 swig 接口(interface)文件中使用了模板,但结果为空。

swig 接口(interface)文件:

%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"

cpp文件
     std::map<int,  std::map<std::string,std::string>> Memberfunction::m;
    std::map<int,  std::map<std::string,std::string>> Memberfunction::getResult()
    {
        return m;
    }

perl 文件
use strict;
use new_tr;
use Data::Dumper;

my $new=new new_tr::some();
print Dumper($new->getResult());

电流输出:
$VAR1 = bless( {}, 'new_tr::StringStringMap' );

期望输出:(多维哈希)
$VAR1 = bless( 0 =>    { 
                                'Brown' => 'Manager', 
                                'Smith' => 'Salesman', 
                                'Albert' => 'Salesman',  
                            },  
            1 =>  { 
                                'Penfold' => 'Designer', 
                                'Evans' => 'Tea-person', 
                                'Jurgens' => 'Manager',  
                            }, 'new_tr::StringStringMap' );

最佳答案

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

new_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"

new_tr.h :
#include <map>
#include <string>
using ssmap = std::map<int,  std::map<std::string,std::string>>;
ssmap getResult();

new_tr.cxx :
#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;
}

然后编译模块:
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 对其进行测试:
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'
                 }
        };

关于c++ - 如何将多维映射从 c++ 转换为 perl 中的哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59676394/

相关文章:

C++ :- Replacing a piece of string by another string

javascript - SWIG 和 Javascript : does embedding the JVM/Rhino into my C++ app is still the only solution?

c++ - 在 Windows 7 中使用用于 Dev-C++ 的 cURL 库时遇到问题

c++ - 从继承中解决循环依赖

c++ - system() 到 c++ 而不调用 cmd.exe

python - swig:如何在 Python 中访问 C 数组

python - 使用 SWIG 的 CPP 到 Python 失败并显示 "error LNK2001: unresolved external symbol"

perl - 如何使用 Data::Section?

perl - WebApp 忽略修补的 perl pm 文件

linux - Perl 编译错误 - make : [pod/perltoc. pod] 段错误