Perl: IPC::可共享和SWIG C++对象不同意

Perl: IPC::Shareable and SWIG'ed C++ object don't agree

本文关键字:C++ 对象 不同意 SWIG 共享 IPC Perl      更新时间:2023-10-16

对于我的某个Perl项目,我需要几个Perl进程共享一些位于c++库中的资源。(不要问,这不是这个问题的核心,只是上下文。)

因此,在这种情况下,我试图深入研究两个"新"领域:IPC::Shareable和使用SWIG包装c++。看来我做错了什么,这正是我想问的。


在c++端,我写了一个小的测试类Rectangle,它有一个空的构造函数、一个set和一个size成员函数。

然后我把这个类包装在swig生成的Perl包example中。

在Perl端,我尝试SWIG模块是否按预期工作:

use example;
my $testrec = new example::Rectangle;
$testrec->set( 6, 7 );
print $testrec->size() . "n";

打印"42",就像它应该的那样。

然后我试着测试我使用IPC::Shareable的方法。我写了两个Perl脚本,一个"服务器"和一个"客户端",来测试资源共享。

"服务器"

:

use IPC::Shareable;
use example;
# v_ for variable, g_ for (IPC) glue
my $v_array;
my $v_rect;
my %options = ( create => 'yes', exclusive => 0, mode => 0644, destroy => 'yes' );
tie $v_array, 'IPC::Shareable', 'g_array', { %options } or die;
tie $v_rect,  'IPC::Shareable', 'g_rect',  { %options } or die;
$v_array = [ "0" ];
$v_rect = new example::Rectangle;
$v_rect->set( 6, 7 );
while ( 1 ) {
    print "server array: " . join( " - ", @$v_array ) . "n";
    print "server rect:  " . $v_rect->size() . "n";
    sleep 3;
}

"客户":

use IPC::Shareable;
use example;
# v_ for variable, g_ for (IPC) glue
my $v_array;
my $v_rect;
my %options = ( create => 0, exclusive => 0, mode => 0644, destroy => 0 );
tie $v_array, 'IPC::Shareable', 'g_array', { %options } or die;
tie $v_rect,  'IPC::Shareable', 'g_rect',  { %options } or die;
my $count = 0;
while ( 1 ) {
    print "client array: " . join( " - ", @$v_array ) . "n";
    print "client rect:  " . $v_rect->size() . "n";
    push( @$v_array, ++$count );
    $v_rect->set( 3, $count );
    sleep 3;
}

从"服务器"开始,然后是"客户端",我得到了"服务器"的输出:

server array: 0
server rect:  42
server array: 0 - 1
server rect:  42
server array: 0 - 1 - 2
server rect:  42

下面是"客户端"的输出:

client array: 0
client rect:  0
client array: 0 - 1
client rect:  3
client array: 0 - 1 - 2
client rect:  6

显然,数组引用得到了共享,但客户端没有"看到"服务器的示例::矩形,而是在(零初始化)的流氓内存上工作,而服务器对此一无所知…

我怀疑我必须对$v_rect做些什么才能使这个工作正常,但我在OO Perl中不够扎实,不知道该怎么做。有人来救援吗?

你想做的事情是行不通的。你必须咬紧牙关,做某种形式的消息传递。

我不太记得SWIG是如何为Perl包装C(++)级对象的,但它很可能是通常的,公认的可怕的"整数槽中的指针"策略。在这个设置中,它将分配一个c++对象,并在Perl标量中存储指向该对象的指针。Perl对象将是对这个标量的引用。当对Perl对象的所有引用都消失时,c++对象将由Perl类的析构函数显式释放。一种更现代的技术是XS::Object::Magic模块允许您做的事情。

但是包装器的细节甚至不是那么重要。重要的是对象对Perl来说是不透明的 !对于连接,IPC::Shareable使用的是有些过时且脆弱的技术。它可能适合您的Perl对象,也可能不适合。但是当您共享Perl对象时,C(++)对象将而不是被共享。怎么可能呢?Perl对此一无所知。也不可能。

您应该从消息传递和序列化的角度来考虑问题。为了序列化C(++)对象,您需要允许C方面的一些合作。看一下Storable模块为序列化对象提供的钩子。就消息传递/队列而言,我喜欢使用ZeroMQ,它为您提供了一个简单的类似套接字的接口。