【问题标题】:swig perl typemap(out) std::vector<std::string> doesn't return the desired output in perlswig perl typemap(out) std::vector<std::string> 不会在 perl 中返回所需的输出
【发布时间】:2019-06-18 02:50:54
【问题描述】:

我正在尝试键入 typemap(out) std::vector。 我希望它以数组的形式获取 perl 代码,而不是我得到一个数组数组,在双重取消引用后包含所需的数据。 如何在 perl 中使其成为字符串数组?

我尝试自己编辑类型图,并在“std_vector.i”和“std_string.i”中使用类型图而不进行编辑,它们都给出了相同的结果。

这是类型映射代码:

%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] = SvPV(sv, $1[x].size());
        }
        AV *myav = av_make(len, svs);
        delete[] svs;
        $result = newRV_noinc((SV*) myav);
        sv_2mortal($result);
        argvi++;
} 

我的输出测试代码:

#this return a std vector<string> in the cpp code
my @commitReturn = $SomeClass->commit();
        print "\n";
        #this should return a string instead it returns an array.
        print $commitReturn[0];
        print "\n";
        #this should not work, instead it returns the desired output.
        print $commitReturn[0][0];

输出是:

ARRAY(0x908c88)
20790

代替:

20790
Can't use string ("20791") as an ARRAY ref while "strict refs"

【问题讨论】:

    标签: c++ perl swig


    【解决方案1】:

    您的commit 方法只是返回一个数组引用,而不是数组引用数组。也许它看起来像一个数组引用数组,因为您将结果分配给一个数组?

    在任何情况下,无需接触类型映射代码,您就可以取消引用函数调用

    @commitReturn = @{$SomeClass->commit()};
    

    或创建一个包装器方法为您取消引用它

    package SomeClass;
    ...
    sub commit_list {
        my $self = shift;
        @{$self->commit()};
    }
    ...
    @commitReturn = $SomeClass->commit_list();
    

    【讨论】:

    • 他们希望代码返回多个字符串,而不是 AoAoString,因此应该是:“您的 commit 方法返回单个标量(对数组的引用),而不是多个字符串。 "
    • 谢谢,但我有一个我无法更改的 api,它使用已编译的 swig 文件,所以我正在寻找一个类型映射解决方案,它将返回预期的内容。意味着只是一个字符串数组。
    【解决方案2】:

    要返回一个数组而不是对数组的引用,您必须操作堆栈,以便 Perl 知道返回了多个标量。

    根据the documentation

    参数堆栈指针的当前值包含在一个 变量argvi。每当增加一个新的输出值时,它是至关重要的 增加这个值。对于多个输出值,最终 argvi 的值应该是输出值的总数。

    所以下面的 typemap 就足够了:

    %typemap(out) std::vector<std::string> {
        int len = $1.size();
        for (int x = 0; x < len; x++) {
            $result = sv_newmortal();
            sv_setpvn($result, $1[x].data(), $1[x].size());
            argvi++;
        }
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-20
      • 1970-01-01
      • 2017-10-19
      相关资源
      最近更新 更多