2

我尝试使用 Perl XS 编写使用 C API 的 perl 代码。我得到对象的转储输出为 -

t_obj 是 - $VAR1 = bless(do{(my $o = 41032464)}, 'Math::Test1' );

我编写了一个名为 Math::Test1 的简单库用于练习,尽管我的模块与此不同且更复杂。

看起来从 perl 到 C 的转换很好,但是当我将数据从 C 中返回到 perl 时,数据处于这种令人困惑的形式,而我期望对象的属性带有一些附加信息。

粘贴我的代码 -

测试1.xs

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"
#include <sys/vfs.h>

typedef struct Num {
    int x;
    int y;
} *Math__Test1;

MODULE = Math::Test1            PACKAGE = Math::Test1

PROTOTYPES:     ENABLE

void
hello()
    CODE:
        printf("Hello World!\n");

Math::Test1
new_xs(class, u, v)
    SV*  class
    int     u
    int     v

    CODE:
    Newz(0, RETVAL, 1, struct Num);
    RETVAL->x = u;
    RETVAL->y = v;
    printf("struct members are %d and %d\n", RETVAL->x, RETVAL->y);

    OUTPUT:
    RETVAL


SV *
display(in)
    Math::Test1  in

    INIT:
        printf("INIT: Section\n");
        printf("number is %d and %d\n", in->x, in->y);

    CODE:
        printf("CODE:Section\n");


int
add(in)
    Math::Test1  in

    CODE:
        RETVAL = in->x + in->y;

    OUTPUT:
        RETVAL

void
DESTROY(self)
        Math::Test1 self
        CODE:
        Safefree(self);

类型图

TYPEMAP

Math::Test1      T_PTROBJ

INPUT

T_PTROBJ

    if(SvROK($arg) && (sv_isa($arg, \"${ntype}\"))) {
        $var = ($type) SvIV((SV*)SvRV($arg));
    } else {
        croak(\"$arg is not reference and type of $type\");
    }

OUTPUT

T_PTROBJ

    sv_setref_pv($arg, \"${ntype}\", (void*) $var);

数学/Test1.pm

package Math::Test1;

use 5.014002;
use strict;
use warnings;

use Data::Dumper;

our $VERSION = '0.01';

require XSLoader;
XSLoader::load('Math::Test1', $VERSION);

use Moose;

has 'a' => (
    is       => 'rw',
    isa      => 'Int',
    required => 1,
);

has 'b' => (
    is       => 'rw',
    isa     => 'Int',
    required => 1,
);

sub new {
   my $self = shift;
   my %arg = @_;
   print "==========CONSTRUCTOR=========\n";
   Math::Test1::new_xs(\$self, $arg{a}, $arg{b});
}

sub addition {
    my $self = shift;
    print "==========ADDITION=========\n";
    my $out = Math::Test1::add($self);
    return $out;
}

sub show {
    my $self = shift;
    print "==========DISPLAY=========\n";
    Math::Test1::display($self);
}
1;

t/t.pl(测试文件)

use strict;
use warnings;

use Data::Dumper;
use Math::Test1;

# create the Test1 object

my $t_obj = Math::Test1->new( a => 5, b => 4 );

print  "t_obj is - " . Dumper($t_obj);

$t_obj->show();

my $c = $t_obj->addition();

print"addition is $c\n";

输出

==========CONSTRUCTOR=========
结构成员是 5 和 4
t_obj 是 - $VAR1 = bless( do{(my $o = 29924112)}, 'Math::Test1 ');
==========显示=========
初始化:节
号为 5 和 4
代码:节
==========添加======== =
加法是 9

我关心的是为什么对象有 bless(do{(my $o = 29924112)}, 'Math::Test1');
我是否错误地解释了输出或 typemap OUTPUT 部分需要更正。

请就此提出您的建议。

4

2 回答 2

2

Perl 对 C 数据结构一无所知,因此您将数据结构的地址 (29924112) 存储到一个有福的标量中。这正是你应该做的。

现在您需要创建访问器以使用该指针访问 C 数据结构(但您创建了一个访问您从未创建的 Moose 对象的 Moose 访问器)。

于 2014-02-03T05:26:30.513 回答
1

您已经编写了它,因此对象被存储为 C 结构,perl 所知道的就是该结构的地址。这并没有错,但是如果不为它们提供 XS 代码,您的属性 a 和 b 将无法正常工作。

从您在另一个答案中的评论来看,听起来您想要两个对象;一个生活在 C 结构中的初始对象,并且在对其执行操作之后,一个 Perl 可访问的对象,不再与原始 C 对象绑定?

于 2014-02-03T04:57:37.010 回答